Bagaimana cara mencari kata Arab dalam teks tanpa diakritik / aksennya?

11

Dalam bahasa Arab seperti dengan beberapa bahasa lain ada yang disebut diakritik untuk meningkatkan pengucapan. Tidak ada konvensi tentang berapa banyak diakritik harus ditulis untuk satu kata. Beberapa menggunakan minimum (yang saya sukai) hanya cukup untuk mengacaukan pengucapan, sedangkan beberapa menggunakannya secara berlebihan atau hanya untuk tujuan kaligrafi estetika. Dengan demikian, ada variasi yang luas tentang apa dan berapa banyak diakritik terkait dengan satu kata. Ketika saya lakukan isearch-forward/backwarddengan menekan C-s/r, masalah muncul ketika saya mengetiknya di mini-buffer pencarian tanpa diakritik itu tidak akan cocok dengan kata yang sama dalam teks jika diakritik, membuat tugas mencari kata ini dengan potensi diakritik yang pernah tidak memuaskan.

Apakah ada cara untuk membuat pencarian / pencarian regexp tidak menyadari diakritik? Saya berharap akan ada jawaban yang dapat diperluas untuk memasukkan regexp C-M-s/rdan grepmencari yang saya gunakan cukup sering di helm-proyektil untuk mencari kata dalam proyek lateks multi-file.

Perbarui
Akan menyenangkan untuk melihat bahwa Emacs di semua fungsi pencariannya melakukan langkah pengupasan pada teks (dari aksen / diakritik / beri nama) sebelum mencocokkan langkah sebagai perilaku default yang mungkin dimatikan oleh awalan saat diminta tidak peduli apa bahasa yang ada. Biasanya, ketika saya mencari sesuatu yang saya tidak harapkan dari editor terbaik (Emacs) gagal dalam tugas ini hanya karena beberapa diakritik atau aksen yang jarang jika pernah diperlukan untuk menyelesaikan tugas-tugas teks biasa.

gelar doktor
sumber
1
Lihatlah ucs-normalize-*fungsi di lisp/international/ucs-normalize.el. Tidak ada lipat pencarian yang telah ditentukan sebelumnya untuk mereka, seperti ada dengan lipat kasus, tetapi Anda setidaknya bisa menormalkan suatu wilayah sebelum mencarinya. Implementasi yang baik mungkin merupakan tugas yang cukup kompleks.
Ted Zlatanov
Bisakah superuser.com/a/675172/233868 membantu?
Nama
@Name, Bahasa Arab memiliki lebih banyak kemungkinan kombinasi huruf (26) dengan aksen / diakritik, jadi bukan untuk bahasa Arab. Tampaknya tidak ada pengganti untuk perpustakaan khusus bahasa. Saya tidak percaya ini sudah diterapkan di Microsoft Word dan bukan di Emacs selama bertahun-tahun yang lalu.
doktoral
1
Bahasa Arab memiliki sekitar 80 diakritik dan 26 huruf, membuat semua kombinasi adalah tugas yang menakutkan. Harus ada beberapa cara untuk menghapus teks diakritiknya, seperti apa yang phpditerapkan: stackoverflow.com/a/25563250/1288722 - juga diterapkan di Javascript: stackoverflow.com/a/7193622/1288722
doktoral
Pikir: apakah tidak mungkin untuk menjalankan string melalui fungsi pembersihan php dan kemudian meneruskan hasilnya ke sesuatu yang mirip helm-swoop?
Sean Allred

Jawaban:

5

Inilah awal yang kasar, berdasarkan daftar penggabungan karakter dalam jawaban ini (dan kemudian diperluas). (Menandai ini sebagai wiki komunitas - harap edit dan perbaiki ini!)

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

Jadi jika buffer berisi "الْحَمْدُ لِلَّهِ رَبِّ الْعَالَمِينَ", dan saya mengevaluasi (arabic-search-without-diacritics "الحمد لله رب العالمين"), ia menemukan teks. Ini juga berfungsi secara interaktif, seperti M-x arabic-search-without-diacritics.

Pendekatan alternatif:

Berikut adalah contoh kode lengkap yang menunjukkan bagaimana tanda diakritik dan nonspacing lainnya ( Mnproperti) dapat dihilangkan dari string yang dinormalisasi dalam kecocokan regexp. Ini bekerja dengan contoh-contoh yang diberikan dan IMO adalah pendekatan yang tepat.

(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
sumber
Saya menambahkan dua diakritik lagi yang biasa digunakan dalam bahasa Arab ke daftar Anda yang bagus. Ini adalah daftar lengkap yang diurutkan 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1648- bebas biaya untuk memperbarui.
doktoral
Fungsi pertama berfungsi dengan arabic-search-without-diacriticsbaik tetapi rusak dengan beberapa kata, saya tidak tahu mengapa seperti ini الأَ. Peringatan lain, saya selalu mengatur-input-metode ke arab ketika saya memasukkan string saya di mini-buffer, sementara dalam isearch-forward/backwardfungsi itu tetap ada.
doktoral
kill-marksadalah pendekatan yang lebih baik untuk menyediakan teks tanpa repot yang siap untuk semua jenis pencarian. Apa yang tidak jelas bagi saya adalah bagaimana mengimplementasikannya pada buffer keseluruhan dan kemudian pada multifile?
doktoral
1
Terima kasih! apakah mungkin untuk menjadikannya seperti isearch-forward/backwardmenyorot semua kejadian dan yang saat ini berbeda dan dengan memohon sakan bergerak maju dan rmundur?
gelar doktor
2
Diskusi tentang emacs-devel: thread.gmane.org/gmane.emacs.devel/182483
Ted Zlatanov