2013-05-09 14 views
35

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

つまり、['LATIN SMALL LETTER A', 'COMBINING ACUTE ACCENT']のようなシーケンスを['LATIN SMALL LETTER A WITH ACUTE']に変換するものは何ですか?私は、もちろん、など、すべての文字を反復処理し、手動交換を行うことができ

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

が、それはありません:今

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

しかし:問題です

参照してください。効率的で、私は特別なケースの半分を逃して間違いを犯すとはかなり確信しています。

答えて

60

unicodedataモジュールを使用すると、NFCフォームに正常化したい、.normalize() functionを提供しています:NFC、または「正規形が作曲」戻り値で構成される文字、NFD、「正規形分解は、」あなたは分解できます

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

、結合された文字。

追加のNFKCおよびNFKD形式は、互換性コードポイントを処理します。例えばU + 2160(ROMAN NUMERAL ONE)は、U + 0049(LATIN CAPITAL LETTER I)と全く同じことですが、Unicode標準では、それらを別々に扱うエンコーディングとの互換性を維持しています。 NFKCまたはNFKD形態のいずれかを使用して、文字を構成または分解に加えて、また、その正規形式ですべての「互換性」の文字を置き換えます:

>>> unicodedata.normalize('NFC', u'\u2167') # roman numeral VIII 
u'\u2167' 
>>> unicodedata.normalize('NFKC', u'\u2167') # roman numeral VIII 
u'VIII' 

は注意構成と分解の形がコミュニケーションであるという保証がないこと。結合された文字をNFC形式に正規化した後、その結果をNFD形式に変換しても、必ずしも同じ文字シーケンスになるとは限りません。 Unicode標準maintains a list of exceptions;このリストの文字は合成可能ですが、さまざまな理由でそれらを結合した形に分解することはできません。 Composition Exclusion Tableのドキュメントも参照してください。

+0

これらの形式の中で、NFCは、「それを表現するために使用できる最も単純なUnicodeエンティティのみを含む」という要件を満たすのに最も近いものです。これは、最小のUnicodeコードポイントを参照するものとして解釈されます。しかし、NFCは他のものにも影響を与える。文字を正規の同等物で置き換えます。 *最小化部分のみを実行するには、あなた自身でプログラムする必要があります。 –