在Ply的正则表达式中如何匹配Unicode?

4

我正在匹配标识符,但现在我有一个问题:我的标识符允许包含Unicode字符。因此,旧的方法已经不够用了:

t_IDENTIFIER = r"[A-Za-z](\\.|[A-Za-z_0-9])*"

在我的标记语言my markup language解析器中,我通过允许除了我明确使用的字符之外的所有字符来匹配Unicode字符,因为我的标记语言只有两个或三个需要逃逸的字符。
如何使用Python正则表达式和PLY匹配所有Unicode字符?这是一个好主意吗?
我希望人们可以在他们的程序中使用像Ω»«°foo² väli π这样的标识符(变量名等)。如果可行的话,我甚至希望人们能用自己的语言编写程序!无论如何,Unicode现在已经得到广泛支持,并且应该会越来越流行。
编辑:Python正则表达式似乎不认识POSIX字符类。
>>> import re
>>> item = re.compile(r'[[:word:]]')
>>> print item.match('e')
None

编辑:为了更好地解释我所需要的内容。我需要一个正则表达式,可以匹配所有Unicode可打印字符,但完全不匹配ASCII字符。
编辑:r“\ w”做了一些我想要的东西,但它不匹配«»,我还需要一个不匹配数字的正则表达式。

似乎Python PCRE也不理解谓词类别:\p{IsAlpha}。 - Axeman
5个回答

5

re 模块支持 \w 语法,如果启用了 UNICODE,它将匹配 [0-9_] 这些字符以及 Unicode 字符属性数据库中被分类为字母数字的字符。

因此,以下示例展示了如何匹配 Unicode 标识符:

>>> import re
>>> m = re.compile('(?u)[^\W0-9]\w*')
>>> m.match('a')
<_sre.SRE_Match object at 0xb7d75410>
>>> m.match('9')
>>> m.match('ab')
<_sre.SRE_Match object at 0xb7c258e0>
>>> m.match('a9')
<_sre.SRE_Match object at 0xb7d75410>
>>> m.match('unicöde')
<_sre.SRE_Match object at 0xb7c258e0>
>>> m.match('ödipus')
<_sre.SRE_Match object at 0xb7d75410>

所以你要查找的表达式是:(?u)[^\W0-9]\w*

现在。这是一个令人满意的解决方案! - Cheery
Python文档中的引用是正确的,但示例是误导性的。您可以简单地使用UNICODE标志与\w代替不必要的长表达式:re.match(r'\w+', "ünıcodê", re.UNICODE) - Walter
2
Walter,你没有正确地阅读问题:1)目标是编程语言中的标识符,通常不以0-9开头。2)解析器(ply)负责解析,无法控制它如何调用匹配,因此需要使用(?u)。 - Florian Bösch
关于控制ply如何调用match函数,请参见下面Stanislav的答案。 - Paul Du Bois

4

在 lex.lex 中,您需要传递参数 reflags:

lex.lex(reflags=re.UNICODE)

1

在 Vinko 的帮助下解决了这个问题。

我意识到获取 Unicode 范围是很愚蠢的。所以我会这样做:

symbols = re.escape(''.join([chr(i) for i in xrange(33, 127) if not chr(i).isalnum()]))
symnums = re.escape(''.join([chr(i) for i in xrange(33, 127) if not chr(i).isalnum()]))

t_IDENTIFIER = "[^%s](\\.|[^%s])*" % (symnums, symbols)

我不了解Unicode字符类。如果这个Unicode的东西开始变得太复杂,我可以只把原来的放回去。UTF-8支持仍然确保在STRING标记上有支持,这更重要。

编辑:另一方面,我开始理解为什么编程语言中没有太多的Unicode支持... 这是一个丑陋的hack,而不是一个令人满意的解决方案。


1

0

它们在Python的正则表达式引擎中不存在。 - Vinko Vrsalovic

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接