Come cercare una parola araba nel testo senza i suoi segni / accenti diacritici?


11

In arabo come in altre lingue c'è quello che viene chiamato segni diacritici per migliorare la pronuncia. Non esiste una convenzione su quanti segni diacritici debbano essere scritti per una sola parola. Alcuni usano il minimo (che preferisco) quanto basta per disambiguare la pronuncia, mentre altri li usano in modo superfluo o solo per scopi estetici calligrafici. Quindi, c'è una grande variazione su cosa e quanti segni diacritici sono associati a una parola. Quando lo faccio isearch-forward/backwardpremendo C-s/r, il problema sorge quando lo scrivo nel mini-buffer di ricerca senza segni diacritici che non corrisponderà alla stessa parola nel testo se avesse segni diacritici, rendendo il compito di cercare questa parola con i suoi potenziali segni diacritici sempre insoddisfacenti.

C'è un modo per rendere la ricerca / regexp inconsapevole dei segni diacritici? Spero che ci sia una risposta che possa essere estesa per includere regexp C-M-s/re grepcercare che uso abbastanza spesso in helm-projectile per cercare una parola in progetti in lattice multi-file.

Aggiornamento
Sarebbe bello vedere che Emacs in tutte le sue funzioni di ricerca sta eseguendo il passaggio di eliminazione del testo (da accenti / segni diacritici / lo chiami) prima di abbinare il passaggio come comportamento predefinito che potrebbe essere disattivato da un prefisso su richiesta non importa quale lingua sia a portata di mano. In genere, quando cerco qualcosa che non mi aspetto dal miglior editore (Emacs) di fallire in questa commissione solo a causa di alcuni segni o accenti che raramente sono mai necessari per eseguire banali faccende di testo.


1
Guarda le ucs-normalize-*funzioni in lisp/international/ucs-normalize.el. Non esiste una piega di ricerca predefinita per quelli, come nel caso della piegatura delle maiuscole, ma puoi almeno normalizzare una regione prima di cercarla. Una buona implementazione è probabilmente un compito abbastanza complesso.
Ted Zlatanov,


@Nome, l'arabo ha molte più possibilità di combinazioni di lettere (26) con accenti / segni diacritici, quindi non è per l'arabo. Sembra che non vi sia alcun sostituto per le librerie specifiche della lingua. Non riesco a credere che questo sia già stato implementato in Microsoft Word e non in Emacs da tanti anni.
dottorato il

1
L'arabo ha circa 80 segni diacritici e 26 lettere, rendendo tutte le combinazioni un compito scoraggiante. Ci deve essere un modo per eliminare il testo dei suoi segni diacritici, come quello phpimplementato: stackoverflow.com/a/25563250/1288722 - implementato anche in Javascript: stackoverflow.com/a/7193622/1288722
dottorato

Pensiero: non è possibile eseguire la stringa attraverso quella funzione di pulizia php e quindi passare il risultato a qualcosa di simile a helm-swoop?
Sean Allred,

Risposte:


5

Ecco un inizio approssimativo, basato sull'elenco di caratteri combinati in questa risposta (e quindi esteso). (Contrassegnando questo come wiki della comunità - per favore modifica e migliora questo!)

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

Quindi se un buffer contiene "الْحَمْدُ لِلَّهِ رَبِّ الْعَالَمِينَ", e io valuto (arabic-search-without-diacritics "الحمد لله رب العالمين"), trova il testo. Funziona anche in modo interattivo, come M-x arabic-search-without-diacritics.

Approccio alternativo:

Ecco un esempio di codice completo che dimostra come i segni diacritici e altri segni non spaziali ( Mnproprietà) possono essere rimossi dalle stringhe normalizzate nelle corrispondenze regexp. Funziona con gli esempi forniti e l'IMO è l'approccio giusto.

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

Ho aggiunto altri due segni diacritici comunemente usati in arabo alla tua bella lista. Questa è la lista completa ordinata 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1648- gratuita per l'aggiornamento.
dottorato il

La prima funzione arabic-search-without-diacriticsfunziona bene ma si rompe con alcune parole, non so perché come questa الأَ. Altro avvertimento, devo sempre impostare il metodo di input in arabo quando inserisco la mia stringa in mini-buffer, mentre in isearch-forward/backwardfunzione rimane lì.
dottorato il

kill-marksè l'approccio migliore per fornire testo senza problemi pronto per tutti i tipi di ricerca. Ciò che non è chiaro per me è come implementarlo su un intero buffer e quindi su più file?
dottorato il

1
Grazie! è possibile farlo isearch-forward/backwardevidenziare tutte le occorrenze e quella attuale in modo diverso e invocando ssi sposta in avanti e si rsposta indietro?
dottorato

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.