Как искать арабское слово в тексте без его диакритики / ударения?

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свойство) могут быть удалены из нормализованных строк в совпадениях с регулярным выражением. Он работает с приведенными примерами, и 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)))
legoscia
источник
Я добавил еще два диакритических знака, обычно используемых на арабском языке, в ваш красивый список. Это полный отсортированный список 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1648- платное обновление.
докторская степень
Первая функция arabic-search-without-diacriticsработает хорошо, но разрывается с некоторыми словами, я не знаю почему, как эта الأَ. Другое предостережение, я всегда должен устанавливать-input-method на арабский, когда я ввожу свою строку в мини-буфер, в то время как в isearch-forward/backwardфункции она остается там.
докторская степень
kill-marksэто лучший подход для обеспечения беспрепятственного текста, готового для всех видов поиска. Что мне неясно, это как реализовать это для всего буфера, а затем для нескольких файлов?
докторская степень
1
Спасибо! возможно ли сделать так, чтобы он как-то isearch-forward/backwardвыделял все вхождения и текущий по-разному, и, вызывая его, sбудет двигаться вперед и rдвигаться назад?
докторская степень
2
Обсуждение emacs-devel: thread.gmane.org/gmane.emacs.devel/182483
Тед Златанов,