在 Python 中匹配 Unicode 字边界
Posted
技术标签:
【中文标题】在 Python 中匹配 Unicode 字边界【英文标题】:Matching Unicode word boundaries in Python 【发布时间】:2017-01-01 03:29:57 【问题描述】:为了匹配 Python 中的 Unicode 字边界 [如 Annex #29 中定义的那样],我一直在使用带有标志 regex.WORD | regex.V1
的 regex
包(regex.UNICODE
应该是默认值,因为该模式是 Unicode字符串)以下列方式:
>>> s="here are some words"
>>> regex.findall(r'\w(?:\B\S)*', s, flags = regex.V1 | regex.WORD)
['here', 'are', 'some', 'words']
在这种相当简单的情况下效果很好。但是,我想知道如果输入字符串包含某些标点符号,预期的行为是什么。在我看来,WB7 表示,例如,x'z
中的撇号不符合作为单词边界的条件,这似乎确实如此:
>>> regex.findall(r'\w(?:\B\S)*', "x'z", flags = regex.V1 | regex.WORD)
["x'z"]
但是,如果有元音,情况就变了:
>>> regex.findall(r'\w(?:\B\S)*', "l'avion", flags = regex.V1 | regex.WORD)
["l'", 'avion']
这表明正则表达式模块实现了注释部分标准中提到的规则WB5a
。但是,这条规则也说行为应该与我无法重现的\u2019
(右单引号)相同:
>>> regex.findall(r'\w(?:\B\S)*', "l\u2019avion", flags = regex.V1 | regex.WORD)
['l’avion']
此外,即使使用“正常”撇号,连字(或 y
)似乎也表现为“非元音”:
>>> regex.findall(r'\w(?:\B\S)*', "l'œil", flags = regex.V1 | regex.WORD)
["l'œil"]
>>> regex.findall(r'\w(?:\B\S)*', "J'y suis", flags = regex.V1 | regex.WORD)
["J'y", 'suis']
这是预期的行为吗? (以上所有示例均使用 regex 2.4.106 和 Python 3.5.2 执行)
【问题讨论】:
【参考方案1】:1- 右单引号’
似乎只是在source file 中被遗漏了:
/* Break between apostrophe and vowels (French, Italian). */
/* WB5a */
if (pos_m1 >= 0 && char_at(state->text, pos_m1) == '\'' &&
is_unicode_vowel(char_at(state->text, text_pos)))
return TRUE;
2- Unicode 元音由is_unicode_vowel()
函数确定,该函数转换为该列表:
a, à, á, â, e, è, é, ê, i, ì, í, î, o, ò, ó, ô, u, ù, ú, û
所以 LATIN SMALL LIGATURE OE œ
字符不被视为 unicode 元音:
Py_LOCAL_INLINE(BOOL) is_unicode_vowel(Py_UCS4 ch)
#if PY_VERSION_HEX >= 0x03030000
switch (Py_UNICODE_TOLOWER(ch))
#else
switch (Py_UNICODE_TOLOWER((Py_UNICODE)ch))
#endif
case 'a': case 0xE0: case 0xE1: case 0xE2:
case 'e': case 0xE8: case 0xE9: case 0xEA:
case 'i': case 0xEC: case 0xED: case 0xEE:
case 'o': case 0xF2: case 0xF3: case 0xF4:
case 'u': case 0xF9: case 0xFA: case 0xFB:
return TRUE;
default:
return FALSE;
这个错误现在在正则表达式 2016.08.27 在bug report 之后得到修复。 [_regex.c:#1668]
【讨论】:
第 1 点确实看起来像一个错误,如果您还没有报告,我建议您报告它。关于第 2 点很难说。在 unicode.org 上搜索“元音”可以找到多种亚洲语言的匹配结果,但没有找到法语或意大利语。 OP 的示例当然看起来是正确的,但我看不到附件 29 专门针对它们。以上是关于在 Python 中匹配 Unicode 字边界的主要内容,如果未能解决你的问题,请参考以下文章
python中sys.setdefaultencoding('utf-8')的作用
python中sys.setdefaultencoding('utf-8')的作用
如何使用 DFA 正则表达式匹配器实现正则表达式断言/环视(即 \b 样式字边界)