如何确定当前字符是否为字母


9

如何确定当前字符是否是字母(字母字符)(即属于[:alpha:]regexp概念中的语法类)。我想编写一个简单的函数,如下所示:

(defun test-letter () (interactive)
(if char-after-is-a-letter
    (message "This is a letter")
    (message "This is not a letter")
    )
)

更新 不幸的是,我对字母类和语法类等效的假设[:alpha:]似乎是错误的。

Answers:


9

使用Unicode字符属性

这绝对应该工作:

(memq (get-char-code-property (char-after) 'general-category)
      '(Ll Lu Lo Lt Lm Mn Mc Me Nl))

作为奖励,它还应该比looking-at


Emacs存储 Unicode标准指定的所有字符属性。可通过访问它们get-char-code-property。具体来说,该general-category属性指定哪些字符是字母(大写,Ll小写,Lu不要问我其他字符是什么)。


非常感谢,这解决了的问题,۱۲۳۴۵۶۷۸۹۰但是有一些真否定词,例如阿拉伯语或希伯来语Alef:אا
命名

@名称固定。再试一次。
马拉巴巴

2
再次感谢你。我检查了各种字母,它的作品。我发现的唯一例外是某些亚洲字母,例如中文en.wikipedia.org/wiki/Chinese_numerals或日语en.wikipedia.org/wiki/Japanese_numerals。例如,将其视为5日语中的数字。您的代码认为这是一封信。也许是字母(例如罗马数字v)。也许熟悉日语的人可以验证这一点。
命名

1
就像英文单词five,所以是字母。当写数字5而不是单词5时,它们的用法5就像英语一样。
Muir18年

8

编辑:这个答案应该在25.5(错误已修复的地方)完全有效。对于较旧的版本,请使用另一个选项


这应该告诉您当前char是否是字母,并且可以使用任何语言。

 (looking-at-p "[[:alpha:]]")

非常感谢,我只是好奇looking-at-p您的解决方案和looking-at其他答案之间的区别。
命名

1
这两个函数是等效的,只是looking-at-p不设置匹配数据。
jch 2015年

1
@Name looking-at-p更接近纯谓词,因为它没有设置匹配数据。如果您以前执行过类似搜索的操作,match-string(及其许多同级对象)将返回搜索结果。同时,对于非谓词版本,match-string将返回查找匹配的结果。
马拉巴巴

5

我认为您可以摆脱这种情况:

(defun test-letter ()
  (interactive)
  (let ((char (char-after)))
    (if (and (eq (char-syntax char) ?w)
             (or (> char ?9)
                 (< char ?1)))
        (message "This is a letter")
      (message "This is not a letter"))))

更新资料

这效率较低,但更接近您想要的:

(defun test-letter ()
  (interactive)
  (if (looking-at "[a-z-A-Z]")
      (message "This is a letter")
    (message "This is not a letter")))

谢谢,一个可能的问题:该函数将数字(123 ...)视为字母。
名称

易于修复。
abo-abo

再次非常感谢。另一个误报:此字符视为۹(例如,印度数字9)或٪字母。
名称

1
您的第一个解决方案可以使用希腊字母(例如ζα),但是更新不可行。
命名

但是将两者结合起来是一个更接近的解决方案。
命名

2

如果您非常关心国家字符和Unicode字符类的精确处理,那么到目前为止,我唯一能找到的解决方案是Python regex。两者grepPerl(让我感到非常惊讶!)都没有正确完成这项工作。

因此,您要使用的正则表达式就是这个:\p{L}。这称为Unicode属性速记版本,完整版本为\p{Letter}甚至p\{General_Category=Letter}Letter本身就是一个复合类,但我不会详谈,我能找到关于这一主题的最好的参考就是这里

Python库不是语言的内置re库(它是内置库的替代方法)。因此,您需要安装它,例如:

# pip install regex

然后,您可以像这样使用它:

import regex
>>> regex.match(ur'\p{L}+', u'۱۲۳۴۵۶۷۸۹۰')
>>> regex.match(ur'\p{L}+', u'абвгд')
<regex.Match object; span=(0, 5), match=u'\u0430\u0431\u0432\u0433\u0434'>
>>> regex.match(ur'\p{L}+', u'123')
>>> regex.match(ur'\p{L}+', u'abcd')
<regex.Match object; span=(0, 4), match=u'abcd'>
>>> 

您也可以将此脚本放在可以访问它的位置:

#!/usr/bin/env python
import regex
import sys

if __name__ == "__main__":
    for match in regex.finditer(ur'\p{L}+', sys.argv[1].decode('utf-8')):
        print match.string

然后像这样从Emacs调用它(假设您将此脚本保存在中~/bin):

(defun unicode-character-p ()
  (interactive)
  (let* ((current (char-after (point)))
         (result (shell-command-to-string
                  (format "~/bin/is-character.py '%c'" current))))
    (message
     (if (string= result "") "Character %c isn't a letter"
        "Character %c is a letter")
     current)))
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.