Ошибка Python re и регулярного выражения после Unicode выше U + D7FB в строке поиска

Я попробовал несколько сопоставлений регулярных выражений Python с Unicode и обнаружил, что они не работают так, как я ожидал, ни в re, ни в регулярных выражениях. Например, r"\w" не соответствует строкам, содержащим "x", если они есть. определенные символы, предшествующие «x» в сопоставляемой строке.

Персонажи, которые кажутся доставляющими неприятности:

  • Неназначенные символы, предшествующие личному использованию (U+D7FC...U+DFFF)

  • Символы частного использования (U+E000...)

Но некоторые неназначенные символы работают нормально (U+0378). И по крайней мере некоторые символы над областью «Частное использование» работают нормально (U+F900).

Я пробовал искать SO, в Интернете, а также в документах re и regex. (например, https://docs.python.org/3.11/library/re.html#module-re и https://pypi.org/project/regex/), но не удалось найти подходящие информация.

Это известное/ожидаемое поведение? Сначала я подумал, может быть, не Unicode символы просто делают совпадение недействительным, и кто-то решил, что Private использование такое же, как и неназначенное; но:

  • U+378 не назначен и работает нормально.

  • Личное использование, конечно, не должно иметь такого поведения, даже если оно было неназначенным.

  • Все работает, когда совпадение удовлетворено до того, как оно увидит шаткого персонажа.

    import sys
    import re
    import unicodedata

    import regex

    def test(theLib):
        print("\nWith %s:" % (theLib.__name__))
        print("x:      ", theLib.match(r"\w", "x"))
        print("0378:   ", theLib.match(r"\w", "x \u0378"))  # Unassigned
        print("E010:   ", theLib.match(r"\w", "\uE010"))  # Private use char
        print("x E010: ", theLib.match(r"\w", "x \uE010"))
        print("E010 x: ", theLib.match(r"\w", "\uE010 x"))
        print("D7FB x: ", theLib.match(r"\w", "\uD7FB x")) # HANGUL JONGSEONG PHIEUPH-THIEUTH
        print("D7FC x: ", theLib.match(r"\w", "\uD7FC x")) # Unassigned
        print("D800 x: ", theLib.match(r"\w", "\uD800 x"))
        print("F900 x: ", theLib.match(r"\w", "\uF900 x"))

    print(sys.version)

    test(re)
    test(regex)

производит:

3.11.9 (main, Apr  2 2024, 08:25:04) [Clang 15.0.0 (clang-1500.3.9.4)]

With re:
x:       <re.Match object; span=(0, 1), match='x'>
0378:    <re.Match object; span=(0, 1), match='x'>
E010:    None
x E010:  <re.Match object; span=(0, 1), match='x'>
E010 x:  None
D7FB x:  <re.Match object; span=(0, 1), match='ퟻ'>
D7FC x:  None
D800 x:  None
F900 x:  <re.Match object; span=(0, 1), match='豈'>

With regex:
x:       <regex.Match object; span=(0, 1), match='x'>
0378:    <regex.Match object; span=(0, 1), match='x'>
E010:    None
x E010:  <regex.Match object; span=(0, 1), match='x'>
E010 x:  None
D7FB x:  <regex.Match object; span=(0, 1), match='ퟻ'>
D7FC x:  None
D800 x:  None
F900 x:  <regex.Match object; span=(0, 1), match='豈'>

🤔 А знаете ли вы, что...
С Python можно создавать кросс-платформенные приложения для Windows, macOS и Linux.


50
1

Ответ:

Решено

Например, r"\w" не соответствует строкам, содержащим "x", если в сопоставляемой строке есть определенные символы, предшествующие "x".

Конечно, он не соответствует «x», если перед ним стоят другие символы. Тогда строка не начинается с «x». А re.match — для сопоставления с самого начала. Итак, на самом деле вы проверяете, соответствует ли \w этим определенным символам.