Як шукати арабське слово в тексті без його діакритики / наголосів?


11

В арабській мові, як і в деяких інших мовах, є те, що називається діакритикою для посилення вимови. Не існує угоди про те, скільки діакритиків слід написати за одне слово. Деякі використовують мінімум (який я вважаю за краще) достатньо, щоб розмежувати вимову, тоді як деякі використовують їх зайво або просто в естетичних каліграфічних цілях. Таким чином, існує велика різниця щодо того, що і скільки діакритиків пов’язано з одним словом. Коли я роблю isearch-forward/backwardнатискання C-s/r, проблема виникає, коли я набираю його в міні-буфері пошуку без діакритики, воно не збігатиметься з тим самим словом у тексті, якби воно було діакритичним, тому завдання пошуку цього слова з його потенційною діакритикою стає завжди незадовільним.

Чи існує спосіб пошуку / повторного пошуку не знати діакритики? Я сподіваюся, що знайдеться відповідь, яку можна розширити на включення regexp C-M-s/rта grepпошук, який я досить часто використовую в кермовому снаряді, щоб шукати слово в багатофайлових проектах з латексу.

Оновлення
Було б добре побачити, що Emacs у всіх своїх пошукових функціях виконує крок відключення тексту (від акцентів / діакритики / ви його називаєте) перед тим, як відповідати кроку як поведінці за замовчуванням, яке може бути вимкнено префіксом на вимогу незалежно від того, яка мова є під рукою. Як правило, коли я шукаю щось, я не сподіваюся, що найкращий редактор (Emacs) зазнає невдачі в цьому дорученні лише через деяку діакритику або акценти, які рідко, якщо коли-небудь знадобляться для виконання мирських завдань з тексту.


1
Подивіться на ucs-normalize-*функції в lisp/international/ucs-normalize.el. Не існує заздалегідь визначеного складання пошуку для таких, як, наприклад, зі складанням регістру, але ви можете принаймні нормалізувати регіон перед його пошуком. Хороша реалізація - це, мабуть, досить складне завдання.
Тед Златанов

Чи може допомогти superuser.com/a/675172/233868 ?
Ім'я

@Name, арабська має набагато більше можливостей поєднання букв (26) з наголосами / діакритикою, тому це не для арабської. Здається, немає заміни бібліотекам, що відповідають мовам. Я не можу повірити, що це вже було впроваджено в Microsoft Word, а не в Emacs всі ті роки тому.
докторантура

1
В арабській мові є близько 80 діакритиків і 26 букв, створення всіх комбінацій є непростим завданням. Повинен бути якийсь спосіб зняти текст його діакритики, як, наприклад, що phpреалізовано: stackoverflow.com/a/25563250/1288722 - також реалізовано в Javascript: stackoverflow.com/a/7193622/1288722
докторат

Думала: чи не можливо запустити рядок через цю функцію очищення php, а потім передати результат чомусь подібному helm-swoop?
Шон Аллред

Відповіді:


5

Ось приблизний початок, заснований на списку поєднання символів у цій відповіді (а потім розширеному). (Позначивши це вікі спільноти - відредагуйте та вдосконаліть це!)

(defconst arabic-diacritics '(#x064b #x064c #x064d #x064e #x064f #x0650 #x0651 #x0652 #x0653 #x0654 #x0655 #x0670)
  "Unicode codepoints for Arabic combining characters.")
(defconst arabic-diacritics-regexp (regexp-opt (mapcar #'string arabic-diacritics)))

(defconst arabic-equivalents
  '(
    ;; "alef" is equivalent to "alef with hamza above" etc
    (#x0627 #x0623 #x0625 #x0622)))

;; (require 'cl-lib)    
;; (defun arabic-strip-diacritics (string)
;;   (cl-reduce (lambda (s c) (remove c s)) arabic-diacritics :initial-value string))

(defun arabic-search-without-diacritics (string)
  (interactive (list (read-string "Search for: " nil nil nil t)))
  (let ((regexp
         (apply #'concat
                (mapcar (lambda (c)
                          (let ((equivalents (assq c arabic-equivalents)))
                            (concat
                             (if equivalents
                                 (regexp-opt (mapcar #'string equivalents))
                               (regexp-quote (string c)))
                             arabic-diacritics-regexp "*")))
                        string))))
    (search-forward-regexp regexp)))

Отже, якщо буфер містить "الْحَمْدُ لِلَّهِ رَبِّ الْعَالَمِينَ", і я оцінюю (arabic-search-without-diacritics "الحمد لله رب العالمين"), він знаходить текст. Він також працює інтерактивно, як M-x arabic-search-without-diacritics.

Альтернативний підхід:

Ось повний приклад коду, який демонструє, як діакритичні та інші нерозмітні знаки ( Mnвластивість) можуть бути видалені з нормалізованих рядків у збігах regexp. Це працює з наведеними прикладами, і IMO - це правильний підхід.

(defun kill-marks (string)
  (concat (loop for c across string
                when (not (eq 'Mn (get-char-code-property c 'general-category)))
                collect c)))

(let* ((original1 "your Arabic string here")
      (normalized1 (ucs-normalize-NFKD-string original1))
      (original2 "your other Arabic string here")
      (normalized2 (ucs-normalize-NFKD-string original2)))
  (equal
   (replace-regexp-in-string "." 'kill-marks normalized1)
   (replace-regexp-in-string "." 'kill-marks normalized2)))

Я додав до свого приємного списку ще дві діакритики, які зазвичай використовуються арабською мовою. Це повний відсортований список 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1648- оновлення безкоштовно.
докторантура

Перша функція arabic-search-without-diacriticsпрацює добре, але розривається з деякими словами, я не знаю, чому подобається ця الأَ. В інших застереженнях, я завжди повинен встановлювати метод введення арабською мовою, коли я ввожу свій рядок у міні-буфер, тоді як у isearch-forward/backwardфункції він залишається там.
докторантура

kill-marksє кращим підходом до надання безпроблемного тексту, готового до всіх видів пошуку. Що мені незрозуміло, як це реалізувати на цілому буфері, а потім на мультифайлах?
докторантура

1
Дякую! чи можна зробити так, щоб isearch-forward/backwardвиділити всі події та поточні по-різному, і натисканням sбуде рухатися вперед і rрухатися назад?
докторантура

2
Обговорення на emacs-devel: thread.gmane.org/gmane.emacs.devel/182483
Тед Златанов
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.