匹配 Unicode 属性的 Python 正则表达式

Perl 和其他一些当前的正则表达式引擎在正则表达式中支持 Unicode 属性,例如类别。例如,在 Perl 中,您可以使用 \p{Ll}来匹配任意小写字母,或者使用 p{Zs}来匹配任何空格分隔符。我在 Python 的2.x 和3.x 代码中都没有看到对此的支持(我深感遗憾)。有没有人知道一个好的策略可以达到类似的效果?我们欢迎本土的解决方案。

18501 次浏览

确实,Python 正则表达式解析器不支持 Unicode 属性类。

如果你想做一个很好的黑客,这将是通常有用的,你可以创建一个预处理器,扫描这样的类标记(\p{M}或其他)的字符串,并替换为相应的字符集,这样,例如,\p{M}将成为 [\u0300–\u036F\u1DC0–\u1DFF\u20D0–\u20FF\uFE20–\uFE2F],和 \P{M}将成为 [^\u0300–\u036F\u1DC0–\u1DFF\u20D0–\u20FF\uFE20–\uFE2F]

人们会感谢你的。 :)

您是否尝试过 波妞古鲁玛,一个到 鬼沼正则表达式引擎的 Python 绑定?在这个引擎中,你可以简单地说 \p{Armenian}来匹配亚美尼亚字符。\p{Ll}\p{Zs}也可以工作。

请注意,虽然 \p{Ll}在 Python 正则表达式中没有等价物,但是 '(?u)\s'应该覆盖 \p{Zs}。 正如文件中所说,“让 w、 W、 b、 b、 d、 d、 s 和 S 依赖于 Unicode字符属性数据库。”\s表示任何间距字符。

您可以在每个字符上煞费苦心地使用 unicodedata:

import unicodedata


def strip_accents(x):
return u''.join(c for c in unicodedata.normalize('NFD', x) if unicodedata.category(c) != 'Mn')

正则表达式模块(标准 re模块的替代品)使用 \p{}语法支持 Unicode 代码点属性。

说到自主开发的解决方案,前段时间我编写了一个小型的 程序来完成这个任务——将编写为 \p{...}的 unicode 类别转换为从 unicode 规格(v. 5.0.0)中提取的一系列值。只支持类别(例如: LZs) ,并且仅限于 BMP。我把它贴在这里,以防有人发现它有用(尽管 Oniguruma 看起来确实是一个更好的选择)。

示例用法:

>>> from unicode_hack import regex
>>> pattern = regex(r'^\\p{Lu}(\\p{L}|\\p{N}|_)*')
>>> print pattern.match(u'疂_1+2').group(0)
疂_1
>>>

这是 来源,还有一个 JavaScript 版本,使用相同的数据。