在Python中匹配Unicode字边界

ewc*_*wcz 13 python regex unicode python-3.x

为了匹配Python 中的Unicode字边界[如附件#29中所定义],我一直在使用regex带有标志的包regex.WORD | regex.V1(regex.UNICODE应该是默认的,因为模式是Unicode字符串),方法如下:

>>> s="here are some words"
>>> regex.findall(r'\w(?:\B\S)*', s, flags = regex.V1 | regex.WORD)
['here', 'are', 'some', 'words']
Run Code Online (Sandbox Code Playgroud)

它在这个相当简单的情况下运行良好.但是,我想知道输入字符串包含某些标点符号时的预期行为是什么.在我看来,WB7说,例如撇号x'z不符合词边界,这似乎确实如此:

>>> regex.findall(r'\w(?:\B\S)*', "x'z", flags = regex.V1 | regex.WORD)
["x'z"]
Run Code Online (Sandbox Code Playgroud)

但是,如果有元音,情况会发生变化:

>>> regex.findall(r'\w(?:\B\S)*', "l'avion", flags = regex.V1 | regex.WORD)
["l'", 'avion']
Run Code Online (Sandbox Code Playgroud)

这表明正则表达式模块实现WB5a了Notes部分标准中提到的规则.但是,这条规则还说行为应该与\u2019(右单引号)相同,我无法重现:

>>> regex.findall(r'\w(?:\B\S)*', "l\u2019avion", flags = regex.V1 | regex.WORD)
['l’avion']
Run Code Online (Sandbox Code Playgroud)

此外,即使使用"普通"撇号,连字符(或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']
Run Code Online (Sandbox Code Playgroud)

这是预期的行为吗?(以上所有示例均使用regex 2.4.106和Python 3.5.2执行)

rev*_*evo 6

1- 右单引号 ’似乎只是在源文件中错过了:

/* 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;
Run Code Online (Sandbox Code Playgroud)

2- Unicode元音由is_unicode_vowel()函数确定,该函数转换为此列表:

a, à, á, â, e, è, é, ê, i, ì, í, î, o, ò, ó, ô, u, ù, ú, û
Run Code Online (Sandbox Code Playgroud)

所以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;
    }
}
Run Code Online (Sandbox Code Playgroud)

现在,在错误报告后,此错误已在regex 2016.08.27中修复.[ _regex.c:#1668 ]

  • 第1点肯定看起来像一个bug,我建议你报告它,如果你还没有.关于第2点很难说.在unicode.org上搜索"元音"会给各种亚洲语言提供一些点击,但是没有关于法语或意大利语的点击.OP的例子当然看似正确,但我看不出附件29具体针对它们. (2认同)