Wie suche ich ein arabisches Wort im Text ohne seine diakritischen Zeichen / Akzente?


11

Im Arabischen gibt es wie in einigen anderen Sprachen sogenannte Diakritika, um die Aussprache zu verbessern. Es gibt keine Konvention darüber, wie viele Diakritika für ein einzelnes Wort geschrieben werden sollen. Einige verwenden das Minimum (das ich bevorzuge) gerade genug, um die Aussprache zu disambiguieren, während andere sie überflüssig oder nur für ästhetische kalligraphische Zwecke verwenden. Daher gibt es große Unterschiede, was und wie viele Diakritika mit einem Wort verbunden sind. Wenn ich isearch-forward/backwarddrücke C-s/r, tritt ein Problem auf, wenn ich es in den Such-Minipuffer ohne diakritische Zeichen eintippe. Wenn es diakritische Zeichen enthält, stimmt es nicht mit demselben Wort im Text überein, sodass die Suche nach diesem Wort mit seinen potenziellen diakritischen Zeichen immer unbefriedigend wird.

Gibt es eine Möglichkeit, die Suche / Regexp-Suche von Diakritika unbewusst zu machen? Ich hoffe, es gibt eine Antwort, die erweitert werden kann, um sie einzuschließen regexp C-M-s/rund zu grepsuchen, die ich ziemlich oft in Steuerprojektilen verwende, um in Latexprojekten mit mehreren Dateien nach einem Wort zu suchen.

Aktualisieren
Es wäre schön zu sehen, dass Emacs in all seinen Suchfunktionen den Abziehschritt für den Text ausführt (von Akzenten / diakritischen Zeichen / Sie nennen ihn), bevor der Schritt als Standardverhalten abgeglichen wird, das bei Bedarf möglicherweise durch ein Präfix deaktiviert wird egal welche Sprache zur Hand ist. Wenn ich nach etwas suche, erwarte ich normalerweise nicht, dass der beste Editor (Emacs) bei diesem Auftrag versagt, nur aufgrund einiger diakritischer Zeichen oder Akzente, die selten oder nie benötigt werden, um alltägliche Textaufgaben zu erledigen.


1
Schauen Sie sich die ucs-normalize-*Funktionen in an lisp/international/ucs-normalize.el. Es gibt keine vordefinierte Suchfaltung für diese, wie dies bei der Fallfaltung der Fall ist, aber Sie können zumindest eine Region normalisieren, bevor Sie sie durchsuchen. Eine gute Implementierung ist wahrscheinlich eine ziemlich komplexe Aufgabe.
Ted Zlatanov


@Name, Arabisch bietet viel mehr Möglichkeiten zur Kombination von Buchstaben (26) mit Akzenten / Diakritika, daher ist es nicht für Arabisch. Es scheint, dass es keinen Ersatz für sprachspezifische Bibliotheken gibt. Ich kann nicht glauben, dass dies bereits vor all den Jahren in Microsoft Word und nicht in Emacs implementiert wurde.
Promotion

1
Arabisch hat ungefähr 80 Diakritika und 26 Buchstaben, alle Kombinationen zu machen ist eine entmutigende Aufgabe. Es muss eine Möglichkeit geben, den Text seiner diakritischen Zeichen zu entfernen , wie in phpimplementiert: stackoverflow.com/a/25563250/1288722 - auch implementiert in Javascript: stackoverflow.com/a/7193622/1288722
Promotion

Gedanke: Ist es nicht möglich, den String durch diese PHP-Bereinigungsfunktion zu führen und das Ergebnis dann an etwas Ähnliches zu übergeben helm-swoop?
Sean Allred

Antworten:


5

Hier ist ein grober Anfang, basierend auf der Liste der kombinierten Zeichen in dieser Antwort (und dann erweitert). (Als Community-Wiki markieren - bitte bearbeiten und verbessern!)

(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)))

Wenn also ein Puffer "الْحَمْدُ لِلَّهِ رَبِّ الْعَالَمِينَ" enthält und ich bewerte (arabic-search-without-diacritics "الحمد لله رب العالمين"), findet er den Text. Es funktioniert auch interaktiv, wie M-x arabic-search-without-diacritics.

Alternativer Ansatz:

Hier ist ein vollständiges Codebeispiel, das zeigt, wie diakritische und andere nicht räumliche Markierungen ( MnEigenschaften) in Regexp-Übereinstimmungen aus normalisierten Zeichenfolgen entfernt werden können. Es funktioniert mit den angegebenen Beispielen und IMO ist der richtige Ansatz.

(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)))

Ich habe Ihrer netten Liste zwei weitere Diakritika hinzugefügt, die üblicherweise auf Arabisch verwendet werden. Dies ist die vollständige sortierte Liste 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1648- kostenlos zu aktualisieren.
Promotion

Die erste Funktion arabic-search-without-diacriticsfunktioniert gut, bricht aber mit einigen Worten ab. Ich weiß nicht, warum ich diese mag الأَ. Andere Einschränkung: Ich muss die Eingabemethode immer auf Arabisch setzen, wenn ich meinen String in einen Minipuffer eingebe, während er in der isearch-forward/backwardFunktion dort bleibt.
Promotion

kill-marksist der bessere Ansatz, um problemlosen Text für alle Arten der Suche bereitzustellen. Was mir unklar ist, ist, wie man das auf einem ganzen Puffer und dann auf mehreren Dateien implementiert?
Promotion

1
Vielen Dank! Ist es möglich, isearch-forward/backwardalle Vorkommen und das aktuelle Ereignis anders hervorzuheben und durch Aufrufen svorwärts und rrückwärts zu bewegen?
Promotion

2
Diskussion über emacs-devel: thread.gmane.org/gmane.emacs.devel/182483
Ted Zlatanov
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.