2013-05-09 112 views
35

在Python中是否有一种标准化方式来标准化unicode字符串,以便它只理解可用于表示它的最简单的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'] 

我当然可以,遍历所有的字符和做手工更换等,但它不是高效率,我敢肯定我会错过一半的特殊情况,并犯错误。

回答

60

unicodedata模块提供了.normalize() function,要归到NFC形式:

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

NFC,或由字符回报,NFD,“范式风化”为您提供了分解“组成范式”,组合字符。

额外的NFKC和NFKD形式处理兼容性代码点;例如U + 2160(ROMAN NUMERAL ONE)实际上与U + 0049(拉丁大写字母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也影响其他事物,例如,用他们的规范等同替换字符。要仅执行*最小化部分,恐怕你必须自己编写它。 – 2013-05-09 20:20:35