在 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']
当然,我可以遍历所有字符并进行手动替换等,但效率不高,而且我很确定我会错过一半的特殊情况并犯错误。
最佳答案
unicodedata
模块提供 .normalize()
function ,您想规范化为 NFC 形式。使用相同 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()
function 以确保使用转义语法打印非 ASCII 代码点,从而明确差异)。
NFC,或“Normal Form Composed”返回组合字符,NFD,“Normal Form Decomposed”为您提供分解的组合字符。
附加的 NFKC 和 NFKD 形式处理兼容性代码点;例如U+2160 ROMAN NUMERAL ONE
实际上与 U+0049 LATIN CAPITAL LETTER I
相同,但存在于 Unicode 标准中以保持与分别处理它们的编码兼容。使用 NFKC 或 NFKD 形式,除了组合或分解字符外,还将所有“兼容”字符替换为其规范形式。
这是一个使用 U+2167 ROMAN NUMERAL EIGHT
代码点的示例;使用 NFKC 形式将其替换为 ASCII V
和 I
字符序列:
>>> unicodedata.normalize('NFC', '\u2167')
'Ⅷ'
>>> unicodedata.normalize('NFKC', '\u2167')
'VIII'
请注意,不能保证组合形式和分解形式是可交换的;将组合字符规范化为 NFC 形式,然后将结果转换回 NFD 形式并不总是会产生相同的字符序列。 Unicode 标准 maintains a list of exceptions ;由于各种原因,此列表中的字符是可组合的,但不能分解回它们的组合形式。另请参阅 Composition Exclusion Table 上的文档。 .
关于python - 规范化 Unicode,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16467479/