Ошибка 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='豈'>

От U+D800 до U+DFFF — это суррогатные символы, которые по отдельности недопустимы.

tripleee 31.08.2024 18:21

@triplee Спасибо, я этого не допустил. Остаются D7FC - D7FF (они меня не сильно беспокоят) и вся область частного использования (которая беспокоит).

TextGeek 31.08.2024 18:23

Я попробую это на других платформах и отредактирую вопрос... Еще раз спасибо!

TextGeek 31.08.2024 18:41

@TextGeek, все результаты выглядят так, как я ожидал, какие из них, по вашему мнению, будут вести себя по-другому и почему вы ожидаете, что они будут вести себя по-другому?

Andj 31.08.2024 23:23

Большинство ваших проблем связано с использованием .match и .search. re.match привязывается к началу строки. Как только вы внесете это изменение, все совпадет, кроме "\uE010".

dawg 31.08.2024 23:46

или re(gex).search

Andj 31.08.2024 23:48

Оууу блин, я чувствую себя тупым. Спасибо, чувак и Анджей!

TextGeek 01.09.2024 21:10
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
0
7
50
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

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

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

Другие вопросы по теме