Python unicodedata

ポータル Python python_encode

since 2011-04-20

http://docs.python.jp/2.7/library/unicodedata.html

Unicode を理解すると何をやってるのかわかってくる。。

Unicode HOWTO http://docs.python.jp/2/howto/unicode.html

  • NFC: normalization form + composed
  • NFKC: NFC + K (=Compatibility) 全角半角など互換文字の変換を行う

normalize

http://tama-san.com/old/document06.html

全角文字を半角文字に正規化できる:

>>> import unicodedata
>>> unicodedata.normalize('NFKC', u'100')
u'100'
>>> unicodedata.normalize('NFKC', u'.')
u'.'
>>> unicodedata.normalize('NFKC', u'・')
u'\u30fb'
>>> unicodedata.normalize('NFKC', u'、')
u'\u3001'
>>> unicodedata.normalize('NFKC', u'A')
u'A'
>>> unicodedata.normalize('NFKC', u'~')
u'~'

一般に「チルダ」「波ダッシュ」のような文字:

>>> '%04x' % ord(u'~')
'007e'
>>> unichr(0x301c)
u'\u301c'
>>> '%04x' % ord(u'~')
'ff5e'

301c は正規化で変換されない:

>>> '%04x' % ord(unicodedata.normalize('NFKC', unichr(0x007e)))
'007e'
>>> '%04x' % ord(unicodedata.normalize('NFKC', unichr(0x301c)))
'301c'
>>> '%04x' % ord(unicodedata.normalize('NFKC', unichr(0xff5e)))
'007e'

ちなみにコマンドプロンプトで下記を実行すると 003f が出てくるが、文字変換に失敗して '?' になったらしい:

>>> '%04x' % ord(u'〜')
'003f'

エンマークは全角¥(0xffe5)を正規化するとバックスラッシュ(0x005c)ではなく Unicode の円記号(0x00a5)に変換される:

>>> '%04x' % ord(u'¥')
'ffe5'
>>> '%04x' % ord(u'\\')
'005c'
>>> unichr(0x00a5)
u'\xa5'
 
>>> '%04x' % ord(unicodedata.normalize('NFKC', unichr(0x00a5)))
'00a5'
>>> '%04x' % ord(unicodedata.normalize('NFKC', unichr(0x005c)))
'005c'
>>> '%04x' % ord(unicodedata.normalize('NFKC', unichr(0xffe5)))
'00a5'

全角バックスラッシュの正規化:

>>> '%04x' % ord(u'\')
'ff3c'
>>> '%04x' % ord(unicodedata.normalize('NFKC', u'\'))
'005c'

全角オーバーライン(?)を正規化すると「空白」と COMBINING MACRON の2文字になる:

>>> '%04x' % ord(u' ̄')
'ffe3'
>>> unicodedata.normalize('NFKC', u' ̄')
u' \u0304'

NFKC (composed) でもNFKD (decomposed) でも同じ結果になる:

>>> '%04x' % ord(unicodedata.normalize('NFKC', u' ̄')[0])
'0020'
>>> '%04x' % ord(unicodedata.normalize('NFKC', u' ̄')[1])
'0304'
 
>>> '%04x' % ord(unicodedata.normalize('NFKD', u' ̄')[0])
'0020'
>>> '%04x' % ord(unicodedata.normalize('NFKD', u' ̄')[1])
'0304'

互換文字の正規化

NFKC と NFC などの違いをみる:

>>> unicodedata.normalize('NFC', u'①')
u'\u2460'
>>> unicodedata.normalize('NFC', u'Ⅱ')
u'\u2161'
>>> unicodedata.normalize('NFD', u'①')
u'\u2460'
>>> unicodedata.normalize('NFD', u'Ⅱ')
u'\u2161'
 
>>> unicodedata.normalize('NFKC', u'①')
u'1'
>>> unicodedata.normalize('NFKC', u'Ⅱ')
u'II'
>>> unicodedata.normalize('NFKD', u'①')
u'1'
>>> unicodedata.normalize('NFKD', u'Ⅱ')
u'II'

サロゲートペア

ちょっと脱線するがサロゲートペアの実験。

𦙾	d859de7e	[ケイ]	ケイコツノ ケイ:ニクヅキニ マタノシタ ツチ

出力するとコードポイント(32ビット)が得られるが、文字の長さは2文字になる:

>>> u'\ud859\ude7e'
u'\U0002667e'
>>> u'\ud859\ude7e'[0]
u'\ud859'
>>> u'\ud859\ude7e'[1]
u'\ude7e'

ちなみにUTF-8では4バイトで表現される:

>>> len(u'\ud859\ude7e'.encode('utf-8'))
4

normalize の影響はない(NFC, NFD, NFKD でも同じ):

>>> unicodedata.normalize('NFKC', u'\ud859\ude7e')
u'\U0002667e'

python_unicodedata.txt · 最終更新: 2013/01/14 12:52 by Takuya Nishimoto
www.chimeric.de Valid CSS Driven by DokuWiki do yourself a favour and use a real browser - get firefox!! Recent changes RSS feed Valid XHTML 1.0