Подтвердить что ты не робот

Согласование границ слова Unicode в Python

Чтобы соответствовать границам слов Юникода [как определено в Приложение № 29] в Python, я использовал пакет 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']

Хорошо работает в этих довольно простых случаях. Тем не менее, мне было интересно, каково ожидаемое поведение, если строка ввода содержит определенную пунктуацию. Мне кажется, что 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']

Это предполагает, что модуль regex реализует правило 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']

Является ли это ожидаемым поведением? (все приведенные выше примеры выполнялись с регулярным выражением 2.4.106 и Python 3.5.2)

4b9b3361

Ответ 1

1-RIGHT SINGLE QUOTATION MARK кажется просто пропущен в исходном файле:

/* 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- Юникодовые гласные определяются с помощью is_unicode_vowel() функции, которая переводится в этот список:

a, à, á, â, e, è, é, ê, i, ì, í, î, o, ò, ó, ô, u, ù, ú, û

Итак, символ LATIN SMALL LIGATURE OE œ не считается гласным в виде юникода:

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;
    }
}

Эта ошибка теперь исправлена ​​в regex 2016.08.27 после отчета об ошибках. [_ regex.c: # 1668]