Python正则表达式\w不匹配组合重音符号?

11 投票
2 回答
2780 浏览
提问于 2025-04-16 00:34

我有一个包含组合音标的UTF8字符串。我想用\w这个正则表达式来匹配它。这个表达式可以匹配带重音的字符,但如果是带组合音标的拉丁字符就匹配不上。

>>> re.match("a\w\w\wz", u"aoooz", re.UNICODE)
<_sre.SRE_Match object at 0xb7788f38>
>>> print u"ao\u00F3oz"
aoóoz
>>> re.match("a\w\w\wz", u"ao\u00F3oz", re.UNICODE)
<_sre.SRE_Match object at 0xb7788f38>
>>> re.match("a\w\w\wz", u"aoo\u0301oz", re.UNICODE)
>>> print u"aoo\u0301oz"
aóooz

(看起来SO的Markdown处理器在处理上面的组合音标时遇到了问题,但最后一行有一个 ́ )

有没有办法让\w也能匹配组合音标呢?我不想规范化文本,因为这个文本是来自文件名的,我不想现在就进行整个“文件名Unicode规范化”。这是Python 2.5的内容。

2 个回答

2

你可以使用 unicodedata.normalize 这个工具,把一些组合的符号合并成一个unicode字符。

>>> import re
>>> from unicodedata import normalize
>>> re.match(u"a\w\w\wz", normalize("NFC", u"aoo\u0301oz"), re.UNICODE)
<_sre.SRE_Match object at 0x00BDCC60>

我知道你说过你不想进行规范化,但我觉得这个解决方案应该没问题,因为你只是对比的字符串进行了规范化,并不需要改变文件名或者其他东西。

7

我刚刚注意到在pypi上有一个新的“regex”包。(如果我理解没错的话,这是一个测试版的新包,未来可能会替代标准库中的re包)。

这个新包似乎在处理unicode方面有更多的可能性。例如,它支持\X,这个用来匹配一个单独的字形(无论它是否使用组合字符)。它还支持根据unicode属性、区块和脚本进行匹配,所以你可以用\p{M}来指代组合标记。之前提到的\X相当于\P{M}\p{M}*(一个不是组合标记的字符,后面跟着零个或多个组合标记)。

需要注意的是,这使得\X在unicode中大致相当于.,而不是\w,所以在你的情况下,\w\p{M}*是你需要的。

目前这个包还不是标准库的一部分,我不知道它的准备情况如何(而且它没有提供二进制版本),但你可以试试看,因为它似乎是你问题的最简单和最“正确”的答案。(否则,我觉得你可能需要明确使用字符范围,就像我在之前回答的评论中提到的那样)。

另外,你可以查看这个页面,里面有关于unicode正则表达式的信息,可能对你有用(也可以作为regex包中一些实现内容的文档)。

撰写回答