86

Python で、Unicode 文字列を正規化して、それを表すために使用できる最も単純な Unicode エンティティのみを理解する標準的な方法はありますか?

つまり、シーケンスを次のよう['LATIN SMALL LETTER A', 'COMBINING ACUTE ACCENT']に変換するものは['LATIN SMALL LETTER A WITH ACUTE']?

問題がどこにあるかを確認します。

>>> import unicodedata
>>> char = "á"
>>> len(char)
1
>>> [ unicodedata.name(c) for c in char ]
['LATIN SMALL LETTER A WITH ACUTE']

でも今:

>>> char = "á"
>>> len(char)
2
>>> [ unicodedata.name(c) for c in char ]
['LATIN SMALL LETTER A', 'COMBINING ACUTE ACCENT']

もちろん、すべての文字を反復処理して手動で置換することもできますが、効率的ではなく、特殊なケースの半分を見逃したり、間違いを犯したりすることは間違いありません。

4

2 に答える 2

120

このunicodedataモジュールは、NFC 形式に正規化する.normalize()機能を提供します。同じ使用例U+0061 LATIN SMALL LETTER-使用したU+0301 A COMBINING ACUTE ACCENT組み合わせとU+00E1 LATIN SMALL LETTER A WITH ACUTEコード ポイント:

>>> print(ascii(unicodedata.normalize('NFC', '\u0061\u0301')))
'\xe1'
>>> print(ascii(unicodedata.normalize('NFD', '\u00e1')))
'a\u0301'

(ここでascii()関数を使用して、 ASCII 以外のコードポイントがエスケープ構文を使用して出力されるようにし、違いを明確にしました)。

NFC、または「Normal Form Composed」は合成された文字を返し、NFD、「Normal Form Decomposed」は分解され、結合された文字を返します。

追加の NFKC および NFKD フォームは、互換性コードポイントを扱います。たとえば、Unicode 標準U+2160 ROMAN NUMERAL ONEとまったく同じですU+0049 LATIN CAPITAL LETTER Iが、それらを個別に扱うエンコーディングとの互換性を維持するために Unicode 標準に存在します。文字の合成または分解に加えて、NFKC または NFKD 形式のいずれかを使用すると、すべての「互換性」文字が正規の形式に置き換えられます。

U+2167 ROMAN NUMERAL EIGHTコードポイントを使用した例を次に示します。NFKC 形式を使用すると、これが ASCIIVI文字のシーケンスに置き換えられます。

>>> unicodedata.normalize('NFC', '\u2167')
'Ⅷ'
>>> unicodedata.normalize('NFKC', '\u2167')
'VIII'

合成された形式と分解された形式が交換可能であるという保証はないことに注意してください。結合された文字を NFC 形式に正規化し、その結果を NFD 形式に変換すると、常に同じ文字シーケンスになるとは限りません。Unicode 標準は、例外のリストを保持しています。このリストの文字は構成可能ですが、さまざまな理由で結合された形式に分解することはできません。成分除外表のドキュメントも参照してください。

于 2013-05-09T17:23:37.403 に答える
8

はい、あります

unicodedata.normalize(form, unistr)

4 つの正規化形式のいずれかを選択する必要があります。

于 2013-05-09T17:23:29.270 に答える