Regex - соответствует персонажу и всем его диакритическим вариациям (иначе говоря, нечувствителен к акценту)
Я пытаюсь сопоставить символ и все его возможные диакритические вариации (или нечувствительный к акценту) с регулярным выражением. Что я мог сделать, конечно:
re.match(r"^[eēéěèȅêęëėẹẽĕȇȩę̋ḕḗḙḛḝė̄]$", "é")
но это не общее решение. Если я использую Unicode категории, такие как \pL
Я не могу уменьшить соответствие конкретному символу, в этом случае e
,
1 ответ
Обходной путь для достижения желаемой цели состоит в том, чтобы сначала использовать unidecode, чтобы избавиться от всех диакритических знаков, а затем просто сопоставить их с обычным e
re.match(r"^e$", unidecode("é"))
Или в этом упрощенном случае
unidecode("é") == "e"
Другое решение, которое не зависит от unidecode-library, сохраняет unicode и дает больше контроля, вручную удаляя диакритические знаки следующим образом:
Используйте unicodedata.normalize(), чтобы превратить вашу входную строку в нормальную форму D (для разложенных), убедившись, что составные символы, такие как é
превратиться в разложенную форму e\u301
(e + комбинированный острый акцент)
>>> input = "Héllô"
>>> input
'Héllô'
>>> normalized = unicodedata.normalize("NFKD", input)
>>> normalized
'He\u0301llo\u0302'
Затем удалите все кодовые точки, которые попадают в категорию Mark, Nonspacing (short Mn
). Это все символы, которые сами по себе не имеют ширины и просто украшают предыдущий символ. Используйте unicodedata.category() для определения категории.
>>> stripped = "".join(c for c in normalized if unicodedata.category(c) != "Mn")
>>> stripped
'Hello'
Результат может быть использован в качестве источника для сопоставления с регулярным выражением, как в примере с unidecode выше. Вот все это как функция:
def remove_diacritics(text):
"""
Returns a string with all diacritics (aka non-spacing marks) removed.
For example "Héllô" will become "Hello".
Useful for comparing strings in an accent-insensitive fashion.
"""
normalized = unicodedata.normalize("NFKD", text)
return "".join(c for c in normalized if unicodedata.category(c) != "Mn")