如何在不带变音符号/重音符号的文本中搜索阿拉伯语单词?


11

阿拉伯语与其他一些语言一样,有变音符号以增强发音。对于一个单词应该写多少个音调符号没有约定。有些人仅使用最小值(我更喜欢)来消除歧义,而有些人则多余地使用它们或仅出于美学目的。因此,与一个单词相关联的发音符号和发音符号存在很大差异。当我isearch-forward/backward按时C-s/r,如果在没有发音符号的情况下在搜索迷你缓冲区中键入该单词,就会出现问题,如果该单词带有发音符号,它将不会与文本中的相同单词匹配,从而使寻找带有潜在发音符号的单词的任务变得不尽人意。

有没有办法使搜索/正则表达式搜索不知道变音符号?我希望会有一个答案可以扩展到包括regexp C-M-s/rgrep搜索,我经常在头盔弹丸中使用它来搜索多文件乳胶项目中的单词。

更新
很高兴看到Emacs在其所有搜索功能中都对文本进行了剥离(从重音符号/变音符号/您命名),然后将其匹配为默认行为,该默认行为可能会按需关闭前缀不管手头有什么语言 通常,当我搜索某些东西时,我并不希望最好的编辑器(Emacs)会因为某些变音符号或重音而失败,而这些变音符号或重音很少用于完成平凡的文本琐事。


1
查看中的ucs-normalize-*功能lisp/international/ucs-normalize.el。没有像针对大小写折叠那样的预定义搜索折叠,但是您至少可以在搜索区域之前对其进行标准化。一个好的实现可能是一个相当复杂的任务。
Ted Zlatanov

superuser.com/a/675172/233868可以提供帮助吗?
命名

@Name,阿拉伯语将字母(26)与重音符号/变音符号结合使用的可能性更大,因此阿拉伯语不适用。似乎没有替代特定语言的库。我真不敢相信,这些年以来,这已经在Microsoft Word中实现了,而在Emacs中还没有实现。
博士学位

1
阿拉伯语大约有80种变音符号和26个字母,使所有组合成为一项艰巨的任务。必须有某种方法来去除其变音符号的文字,例如已php实现的:stackoverflow.com/a/25563250/1288722-也已实现在Javascriptstackoverflow.com/a/7193622/1288722
博士学位

想法:是否不可能通过该php清理函数运行字符串,然后将结果传递给类似的东西helm-swoop
肖恩·艾瑞德

Answers:


5

这是一个粗略的开始,基于此答案中组合字符的列表(然后扩展)。(将其标记为社区Wiki-请对此进行编辑和改进!)

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

我在您的清单中又添加了两个阿拉伯语常用的变音符号。这是完整的排序列表1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1648-免费更新。
博士学位

第一个功能arabic-search-without-diacritics运行良好,但有些单词打断了,我不知道为什么会这样الأَ。其他警告,当我在迷你缓冲区中输入字符串时,我必须始终将输入法设置为阿拉伯语,而在isearch-forward/backward功能上它仍保留在那里。
博士学位

kill-marks是提供可用于各种搜索的无忧文本的更好方法。我不清楚的是如何在整个缓冲区上然后在多文件上实现它?
博士学位

1
谢谢!是否有可能使它像isearch-forward/backward突出显示所有事件一样,并以不同方式突出显示当前事件,并且通过调用s将向前和r向后移动?
博士学位

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.