Как предложил Виктор в комментариях, вы можете использовать (?U)
для включения флага UNICODE_CHARACTER_CLASS
. Хотя это позволяет сопоставить äöa
, это все еще не соответствует m²
. Это потому, что UNICODE_CHARACTER_CLASS
с \w
не распознает ²
как допустимый буквенно-цифровой символ. В качестве замены \w
можно использовать [\pN\pL_]
. Это соответствует числам Юникода \pN
и буквам Юникода \pL
(плюс _
). Класс символов \pN
Unicode включает класс символов \pNo
, который включает в себя класс символов Дополнение к латинице 1 — пунктуация и символы Latin-1 (в него входит ²³¹
). В качестве альтернативы вы можете просто добавить класс символов Unicode \pNo
в класс символов с \w
. Это означает, что следующие регулярные выражения правильно соответствуют вашим строкам:
[\pN\pL_]{2,} # Matches any Unicode number or letter, and underscore
(?U)[\w\pNo]{2,} # Uses UNICODE_CHARACTER_CLASS so that \w matches Unicode.
# Adds \pNo to additionally match ²³¹
Так почему же \w
не соответствует ²
в Java, но соответствует в Python?
интерпретация Java
Глядя на Реализация OpenJDK 8-b132 Pattern
, мы получаем следующую информацию (я удалил информацию, не имеющую отношения к ответу на вопрос):
Поддержка Юникода
Следующие предопределенные классы символов и классы символов POSIX соответствуют рекомендациям Приложения C: свойства совместимости регулярных выражений Unicode< /em>, если указан флаг UNICODE_CHARACTER_CLASS
.
\w
Словесный символ: [\p{Alpha}\p{gc=Mn}\p{gc=Me}\p{gc=Mc}\p{Digit}\p{gc=Pc}\p{IsJoin_Control}]
Здорово! Теперь у нас есть определение для \w
при использовании флага (?U)
. Включив эти классы символов Unicode в этот замечательный инструмент, вы точно узнаете, что каждый из эти классы символов Unicode совпадают. Не делая этот пост слишком длинным, я просто скажу вам, что ни один из следующих классов не соответствует ²
:
\p{Alpha}
\p{gc=Mn}
\p{gc=Me}
\p{gc=Mc}
\p{Digit}
\p{gc=Pc}
\p{IsJoin_Control}
интерпретация Python
Так почему же Python соответствует ²³¹
, когда флаг u
используется вместе с \w
? Это было очень сложно отследить, но я покопался в исходном коде Python (я использовал Python 3.6. 5rc1 - 13.03.2018). После удаления большого количества пуха о том, как это называется, в основном происходит следующее:
\w
определяется как CATEGORY_UNI_WORD
, к которому затем добавляется префикс SRE_
. SRE_CATEGORY_UNI_WORD
звонит SRE_UNI_IS_WORD(ch)
SRE_UNI_IS_WORD
определяется как (SRE_UNI_IS_ALNUM(ch) || (ch) == '_')
.
SRE_UNI_IS_ALNUM
вызывает Py_UNICODE_ISALNUM
, который, в свою очередь, определяется как (Py_UNICODE_ISALPHA(ch) || Py_UNICODE_ISDECIMAL(ch) || Py_UNICODE_ISDIGIT(ch) || Py_UNICODE_ISNUMERIC(ch))
.
- Важным здесь является
Py_UNICODE_ISDECIMAL(ch)
, определяемый как Py_UNICODE_ISDECIMAL(ch) _PyUnicode_IsDecimalDigit(ch)
.
Теперь давайте посмотрим на метод _PyUnicode_IsDecimalDigit(ch)
:
int _PyUnicode_IsDecimalDigit(Py_UCS4 ch)
{
if (_PyUnicode_ToDecimalDigit(ch) < 0)
return 0;
return 1;
}
Как мы видим, этот метод возвращает 1
, если _PyUnicode_ToDecimalDigit(ch) < 0
. Так как же выглядит _PyUnicode_ToDecimalDigit
?
int _PyUnicode_ToDecimalDigit(Py_UCS4 ch)
{
const _PyUnicode_TypeRecord *ctype = gettyperecord(ch);
return (ctype->flags & DECIMAL_MASK) ? ctype->decimal : -1;
}
Отлично, в основном, если байт символа в кодировке UTF-32 имеет флаг DECIMAL_MASK
, это будет оценено как true, и будет возвращено значение, большее или равное 0
.
Значение байта в кодировке UTF-32 для ²
равно 0x000000b2
, а наш флаг DECIMAL_MASK
равен 0x02
. 0x000000b2 & 0x02
оценивается как true, поэтому ²
считается допустимым буквенно-цифровым символом Unicode в python, поэтому \w
с флагом u
соответствует ²
.
person
ctwheels
schedule
21.03.2018
"(?U)\\b\\w\\w+\\b"
или просто"(?U)\\w{2,}"
- person Wiktor Stribiżew   schedule 21.03.2018äöa
, но не работает дляm²
- person ctwheels   schedule 21.03.2018\w
в регулярном выражении Java соответствует тем же символам, что и Unicode\w
в Python? - person Wiktor Stribiżew   schedule 21.03.2018²,½,³
. - person Daniel Kirchner   schedule 21.03.2018(?U)
, теперь отсутствуют только экспоненты и дроби. - person Daniel Kirchner   schedule 21.03.2018"(?U)[\\w\\p{No}]{2,}"
. - person Wiktor Stribiżew   schedule 21.03.2018