文字とそのすべての可能な分音記号のバリエーション (アクセントを区別しない) を正規表現と一致させようとしています。もちろん、私ができることは次のとおりです。
re.match(r"^[eēéěèȅêęëėẹẽĕȇȩę̋ḕḗḙḛḝė̄]$", "é")
しかし、それは一般的な解決策ではありません。この場合\pL
、一致を特定の文字に減らすことはできませんe
。
文字とそのすべての可能な分音記号のバリエーション (アクセントを区別しない) を正規表現と一致させようとしています。もちろん、私ができることは次のとおりです。
re.match(r"^[eēéěèȅêęëėẹẽĕȇȩę̋ḕḗḙḛḝė̄]$", "é")
しかし、それは一般的な解決策ではありません。この場合\pL
、一致を特定の文字に減らすことはできませんe
。
望ましい目標を達成するための回避策は、最初にユニコードを使用してすべての分音記号を取り除き、次に通常の記号と一致させることです。e
re.match(r"^e$", unidecode("é"))
または、この単純化されたケースでは
unidecode("é") == "e"
unidecode-library に依存せず、unicode を保持し、より多くの制御を提供する別の解決策は、次のように分音記号を手動で削除することです。
unicodedata.normalize()を使用して、入力文字列を通常の形式 D (分解) に変換し、複合文字é
が分解された形式e\u301
(e + COMBINING ACUTE ACCENT)に変換されるようにします。
>>> 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")