2.9 將Unicode文本標(biāo)準(zhǔn)化

2018-02-24 15:26 更新

問題

你正在處理Unicode字符串,需要確保所有字符串在底層有相同的表示。

解決方案

在Unicode中,某些字符能夠用多個(gè)合法的編碼表示。為了說明,考慮下面的這個(gè)例子:

>>> s1 = 'Spicy Jalape\u00f1o'
>>> s2 = 'Spicy Jalapen\u0303o'
>>> s1
'Spicy Jalape?o'
>>> s2
'Spicy Jalape?o'
>>> s1 == s2
False
>>> len(s1)
14
>>> len(s2)
15
>>>

這里的文本”Spicy Jalape?o”使用了兩種形式來表示。第一種使用整體字符”?”(U+00F1),第二種使用拉丁字母”n”后面跟一個(gè)”~”的組合字符(U+0303)。

在需要比較字符串的程序中使用字符的多種表示會(huì)產(chǎn)生問題。為了修正這個(gè)問題,你可以使用unicodedata模塊先將文本標(biāo)準(zhǔn)化:

>>> import unicodedata
>>> t1 = unicodedata.normalize('NFC', s1)
>>> t2 = unicodedata.normalize('NFC', s2)
>>> t1 == t2
True
>>> print(ascii(t1))
'Spicy Jalape\xf1o'
>>> t3 = unicodedata.normalize('NFD', s1)
>>> t4 = unicodedata.normalize('NFD', s2)
>>> t3 == t4
True
>>> print(ascii(t3))
'Spicy Jalapen\u0303o'
>>>

normalize() 第一個(gè)參數(shù)指定字符串標(biāo)準(zhǔn)化的方式。NFC表示字符應(yīng)該是整體組成(比如可能的話就使用單一編碼),而NFD表示字符應(yīng)該分解為多個(gè)組合字符表示。

Python同樣支持?jǐn)U展的標(biāo)準(zhǔn)化形式NFKC和NFKD,它們?cè)谔幚砟承┳址臅r(shí)候增加了額外的兼容特性。比如:

>>> s = '\ufb01' # A single character
>>> s
'?'
>>> unicodedata.normalize('NFD', s)
'?'
# Notice how the combined letters are broken apart here
>>> unicodedata.normalize('NFKD', s)
'fi'
>>> unicodedata.normalize('NFKC', s)
'fi'
>>>

討論

標(biāo)準(zhǔn)化對(duì)于任何需要以一致的方式處理Unicode文本的程序都是非常重要的。當(dāng)處理來自用戶輸入的字符串而你很難去控制編碼的時(shí)候尤其如此。

在清理和過濾文本的時(shí)候字符的標(biāo)準(zhǔn)化也是很重要的。比如,假設(shè)你想清除掉一些文本上面的變音符的時(shí)候(可能是為了搜索和匹配):

>>> t1 = unicodedata.normalize('NFD', s1)
>>> ''.join(c for c in t1 if not unicodedata.combining(c))
'Spicy Jalapeno'
>>>

最后一個(gè)例子展示了 unicodedata 模塊的另一個(gè)重要方面,也就是測(cè)試字符類的工具函數(shù)。combining() 函數(shù)可以測(cè)試一個(gè)字符是否為和音字符。在這個(gè)模塊中還有其他函數(shù)用于查找字符類別,測(cè)試是否為數(shù)字字符等等。

Unicode顯然是一個(gè)很大的主題。如果想更深入的了解關(guān)于標(biāo)準(zhǔn)化方面的信息,請(qǐng)看考 Unicode官網(wǎng)中關(guān)于這部分的說明 [http://www.unicode.org/faq/normalization.html]Ned Batchelder在 他的網(wǎng)站 [http://nedbatchelder.com/text/unipain.html]上對(duì)Python的Unicode處理問題也有一個(gè)很好的介紹。

以上內(nèi)容是否對(duì)您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)