2009-12-02 71 views
48

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

+10

实际上,Perl支持所有的** Unicode属性,而不仅仅是一般的类别。例子包括:\ p {Block = Greek},\ p {Script = Armenian},\ p {General_Category = Uppercase_Letter},\ p {White_Space},\ p {Alphabetic},\ p {Math},\ p {Bidi_Class = Right_to_Left},\ p {Word_Break = A_Letter },\ p {Numeric_Value = 10},\ p {Hangul_Syllable_Type = Leading_Jamo},\ p {Sentence_Break = SContinue}只有Perl和ICU的正则表达式才能涵盖完整的Unicode属性。每个人都会涉及一小部分,通常对于最小的Unicode工作来说还不够。 – tchrist 2011-04-25 23:03:07

回答

22

您是否试过Ponyguruma,一个Python与Oniguruma正则表达式引擎绑定?在该引擎中,您可以简单地说\p{Armenian}以匹配亚美尼亚字符。 \p{Ll}\p{Zs}也可以。

+2

这个模块与Python re模块有不一样的API – 2012-05-20 20:06:47

+7

最后承诺Ponyguruma模块显然是2010年( http://dev.pocoo.org/hg/sandbox/ponyguruma)而PyPI上的Python正则表达式模块是积极开发的:http://pypi.python.org/pypi/regex – RichVel 2013-09-18 13:04:20

4

你说得对,Python属性类不被Python正则表达式解析器支持。

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

人们会感谢你。 :)

+1

正确的是,创造人物课程横跨了我的想法。但大约有40个类别,你最终会生成80个类,这不包括unicode脚本,块,平面和其他类。可能值得一个小开源项目,但仍然是一个维护噩梦。我刚刚发现re.VERBOSE不适用于字符类,所以这里没有评论或空白空间来帮助可读性... – ThomasH 2009-12-02 15:17:51

2

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

+0

你是对的。问题是,'(?u)\ s'大于'\ p {Zs}',包括例如新队。所以如果你真的只想匹配空间分隔符,前者会过度生成。 – ThomasH 2009-12-07 21:32:49

+3

@ThomasH:要获得“空格,除非不换行”,您可以使用双否定字符类:'(?u)[^ \ S \ n]' – bukzor 2012-03-22 22:12:01

6

可以精心上每个字符使用unicodedata:

import unicodedata 

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

谢谢。虽然外面的正则表达式,这可能是某些情况下可行的替代方案。 – ThomasH 2010-11-13 21:09:27

+0

似乎Python'unicodedata'模块目前不包含例如字符的脚本或Unicode块。另请参阅https://stackoverflow.com/questions/48058402/unicode-table-information-about-a-character-in-python/48060112#48060112 – tripleee 2018-01-10 06:44:17

52

regex模块(到标准re模块的替代)支持带有\p{}语法的Unicode编码点的属性。

+1

不确定''\ p {}''支持的完整性如何,但是这个模块是积极开发的,并且最终应该替换内置的''re''模块:参见http://pypi.python.org/pypi/regex – RichVel 2013-09-18 13:05:42

+4

+1:'regex'是stdlib的一个直接替代品're'模块。如果你知道如何使用're';你马上可以使用'regex'。 '将regex导入为re'并且你有'\ p {}'语法支持。下面是一个[示例如何使用'\ p {P}']删除字符串中的所有标点符号(http://stackoverflow.com/a/11066687) – jfs 2013-12-21 02:11:34

5

说到自制的解决方案的,前一段时间我写了一个小program能够做到这一点 - 转换写成\p{...}到值的范围为Unicode类别,该Unicode specification(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 
>>> 

这里的source。还有一个JavaScript version,使用相同的数据。

+1

不错的一个,尽管您使用的是手工制作的文字在代码中。这些文字是从规范的某些文本形式生成的,这将是很好的。或者从unicodedata(http://docs.python.org/library/unicodedata.html#module- unicodedata)。您可能可以运行所有有效的unicode代码点并通过unicodedata.category()运行它们,并使用输出来填充地图... – ThomasH 2012-03-06 17:43:17

+0

感谢您的提示,我可能会在某一天实现这一点。上面的代码首先是为JavaScript创建的(当时没有什么明智的选择),然后移植到Python。我在规格上运行了一些正则表达式,并用一次性脚本完成,但我同意一个可重复的过程本来会更好,所以我可以保持它最新的。 – mgibsonbr 2012-03-07 00:52:10

+0

我已经破解了一个动态构建地图的快速函数(只有字符列表作为值): def unicats(maxu): m = defaultdict(列表) 我在范围内(maxu): 尝试:cat = unicodedata.category(unichr(i)) 除外:cat =无 if cat:m [cat] .append(i) return m m = unicats(10FFFF) 请注意,某些类别会变得非常大(例如len(m ['Cn'])== 873882)。 – ThomasH 2012-03-07 09:09:56