Я попробовал несколько сопоставлений регулярных выражений 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='豈'>
@triplee Спасибо, я этого не допустил. Остаются D7FC - D7FF (они меня не сильно беспокоят) и вся область частного использования (которая беспокоит).
Я попробую это на других платформах и отредактирую вопрос... Еще раз спасибо!
@TextGeek, все результаты выглядят так, как я ожидал, какие из них, по вашему мнению, будут вести себя по-другому и почему вы ожидаете, что они будут вести себя по-другому?
Большинство ваших проблем связано с использованием .match
и .search
. re.match привязывается к началу строки. Как только вы внесете это изменение, все совпадет, кроме "\uE010"
.
или re(gex).search
Оууу блин, я чувствую себя тупым. Спасибо, чувак и Анджей!
Например, r"\w" не соответствует строкам, содержащим "x", если в сопоставляемой строке есть определенные символы, предшествующие "x".
Конечно, он не соответствует «x», если перед ним стоят другие символы. Тогда строка не начинается с «x». А re.match
— для сопоставления с самого начала. Итак, на самом деле вы проверяете, соответствует ли \w
этим определенным символам.
От U+D800 до U+DFFF — это суррогатные символы, которые по отдельности недопустимы.