Jak wyszukiwać arabskie słowo w tekście bez znaków diakrytycznych / akcentów?

11

W języku arabskim, podobnie jak w niektórych innych językach, istnieje tak zwane znaki diakrytyczne w celu poprawy wymowy. Nie ma konwencji dotyczącej liczby znaków diakrytycznych dla jednego słowa. Niektórzy używają minimum (które preferuję) na tyle, aby jednoznacznie wymawiać, podczas gdy inni używają ich zbytecznie lub po prostu dla celów estetycznych kaligrafii. Tak więc istnieje duża różnorodność tego, co i ile znaków diakrytycznych jest powiązanych z jednym słowem. Kiedy robię to isearch-forward/backwardprzez naciśnięcie C-s/r, problem pojawia się, gdy wpisuję go w minibuforze wyszukiwania bez znaków diakrytycznych, nie będzie pasował do tego samego słowa w tekście, jeśli miał znaki diakrytyczne, co sprawi, że zadanie szukania tego słowa z jego potencjalnymi znakami diakrytycznymi będzie zawsze niezadowalające.

Czy istnieje sposób, aby wyszukiwanie / wyrażenia regularne nie były świadome znaków diakrytycznych? Mam nadzieję, że znajdzie się odpowiedź, która może zostać rozszerzona o wyszukiwanie regexp C-M-s/ri grepwyszukiwanie, którego dość często używam w pocisku steru, aby szukać słowa w wieloplikowych projektach lateksowych.

Aktualizacja
Byłoby miło zobaczyć, że Emacs we wszystkich swoich funkcjach wyszukiwania wykonuje krok usuwania tekstu (od akcentów / znaków diakrytycznych / jak go nazywacie) przed dopasowaniem kroku jako domyślnego zachowania, które może zostać wyłączone przez prefiks na żądanie bez względu na to, jaki język jest pod ręką. Zazwyczaj, gdy szukam czegoś, nie oczekuję, że najlepszy redaktor (Emacs) zawiedzie w tym zadaniu tylko z powodu niektórych znaków diakrytycznych lub akcentów, które rzadko, jeśli w ogóle, są potrzebne do wykonywania zwykłych obowiązków tekstowych.

doktorat
źródło
1
Spójrz na ucs-normalize-*funkcje w lisp/international/ucs-normalize.el. Dla tych nie ma wstępnie zdefiniowanego składania wyszukiwania, tak jak w przypadku składania liter, ale można przynajmniej znormalizować region przed jego przeszukaniem. Dobre wdrożenie jest prawdopodobnie dość złożonym zadaniem.
Ted Zlatanov
Czy superuser.com/a/675172/233868 może pomóc?
Imię i nazwisko
@Name, arabski ma znacznie więcej możliwości kombinacji liter (26) z akcentami / znakami diakrytycznymi, więc nie jest to język arabski. Wydaje się, że nie ma substytutu dla bibliotek specyficznych dla języka. Nie mogę uwierzyć, że zostało to już zaimplementowane w Microsoft Word, a nie w Emacsie przez te wszystkie lata wstecz.
doktorat
1
Arabski ma około 80 znaków diakrytycznych i 26 liter, dlatego wszystkie kombinacje to trudne zadanie. Musi być jakiś sposób na usunięcie tekstu jego znaków diakrytycznych, na przykład phpzaimplementowane: stackoverflow.com/a/25563250/1288722 - również zaimplementowane w Javascript: stackoverflow.com/a/7193622/1288722
doktorat
Myśl: czy nie jest możliwe przeprowadzenie ciągu przez tę funkcję czyszczenia php, a następnie przekazanie wyniku do czegoś podobnego helm-swoop?
Sean Allred

Odpowiedzi:

5

Oto trudny początek, oparty na liście łączących znaki w tej odpowiedzi (a następnie rozszerzonej). (Oznaczając to jako wiki społeczności - edytuj i popraw to!)

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

Więc jeśli bufor zawiera „الْحَمْدُ لِلَّهِ رَبِّ الْعَالَمِينَ” i oceniam (arabic-search-without-diacritics "الحمد لله رب العالمين"), to znajduje tekst. Działa również interaktywnie, jak M-x arabic-search-without-diacritics.

Alternatywne podejście:

Oto pełny przykład kodu, który pokazuje, w jaki sposób znaki diakrytyczne i inne znaki spacji ( Mnwłaściwość) można usunąć ze znormalizowanych ciągów w dopasowaniach wyrażeń regularnych . Działa z podanymi przykładami, a IMO jest właściwym podejściem.

(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
źródło
Do twojej ładnej listy dodałem jeszcze dwa znaki diakrytyczne powszechnie używane w języku arabskim. To jest kompletna lista posortowana 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1648- aktualizacja bezpłatna.
doktorat
Pierwsza funkcja arabic-search-without-diacriticsdziała dobrze, ale łamie się z pewnymi słowami, nie wiem dlaczego tak الأَ. Innym zastrzeżeniem jest to, że zawsze muszę ustawić metodę wprowadzania na arabską, kiedy wprowadzam ciąg znaków do mini-bufora, podczas gdy w isearch-forward/backwardfunkcji pozostaje tam.
doktorat
kill-marksto lepsze podejście do zapewnienia bezproblemowego tekstu gotowego do wszelkiego rodzaju wyszukiwania. Nie jest dla mnie jasne, jak zaimplementować to w całym buforze, a następnie w plikach wielu?
doktorat
1
Dzięki! czy jest możliwe, aby isearch-forward/backwardwyróżnić wszystkie wystąpienia i bieżące inaczej, a wywoływanie sspowoduje przejście do przodu i rdo tyłu?
doktorat
2
Dyskusja na temat emacs-devel: thread.gmane.org/gmane.emacs.devel/182483
Ted Zlatanov