【问题标题】:Matching Unicode word boundaries in Python在 Python 中匹配 Unicode 字边界
【发布时间】:2017-01-01 03:29:57
【问题描述】:

为了匹配 Python 中的 Unicode 字边界 [如 Annex #29 中定义的那样],我一直在使用带有标志 regex.WORD | regex.V1regex 包(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 执行)

【问题讨论】:

    标签: python regex python-3.x unicode


    【解决方案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 专门针对它们。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-02-13
    • 1970-01-01
    • 2012-05-22
    • 1970-01-01
    相关资源
    最近更新 更多