目次

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

<html> <div class="amazlet-box" style="margin-bottom:0px;"><div class="amazlet-image" style="float:left;margin:0px 12px 1px 0px;"><a href="http://www.amazon.co.jp/exec/obidos/ASIN/477414164X/r4wh-22/ref=nosim/" name="amazletlink" target="_blank"><img src="http://ecx.images-amazon.com/images/I/51b7R1hZL-L._SL160_.jpg" alt="プログラマのための文字コード技術入門 (WEB+DB PRESS plus) (WEB+DB PRESS plusシリーズ)" style="border: none;" /></a></div><div class="amazlet-info" style="line-height:120%; margin-bottom: 10px"><div class="amazlet-name" style="margin-bottom:10px;line-height:120%"><a href="http://www.amazon.co.jp/exec/obidos/ASIN/477414164X/r4wh-22/ref=nosim/" name="amazletlink" target="_blank">プログラマのための文字コード技術入門 (WEB+DB PRESS plus) (WEB+DB PRESS plusシリーズ)</a><div class="amazlet-powered-date" style="font-size:80%;margin-top:5px;line-height:120%">posted with <a href="http://www.amazlet.com/" title="amazlet" target="_blank">amazlet</a> at 13.01.13</div></div><div class="amazlet-detail">矢野 啓介 <br />技術評論社 <br />売り上げランキング: 14,076<br /></div><div class="amazlet-sub-info" style="float: left;"><div class="amazlet-link" style="margin-top: 5px"><a href="http://www.amazon.co.jp/exec/obidos/ASIN/477414164X/r4wh-22/ref=nosim/" name="amazletlink" target="_blank">Amazon.co.jp で詳細を見る</a></div></div></div><div class="amazlet-footer" style="clear: left"></div></div> </html>

Text Processing in Python by David Mertz – published by Addison Wesley

スペース

「スペース」の category を見てみた:

http://ja.wikipedia.org/wiki/%E3%82%B9%E3%83%9A%E3%83%BC%E3%82%B9

>>> unicodedata.category(u'\u0020')
'Zs'
>>> unicodedata.category(u'\u00a0')
'Zs'
>>> unicodedata.category(u'\u2002')
'Zs'
>>> unicodedata.category(u'\u2003')
'Zs'
>>> unicodedata.category(u'\u2004')
'Zs'
>>> unicodedata.category(u'\u2005')
'Zs'
>>> unicodedata.category(u'\u2009')
'Zs'
>>> unicodedata.category(u'\u2006')
'Zs'
>>> unicodedata.category(u'\u2007')
'Zs'
>>> unicodedata.category(u'\u2008')
'Zs'
>>> unicodedata.category(u'\u200a')
'Zs'
>>> unicodedata.category(u'\u200b')
'Cf'
>>> unicodedata.category(u'\u3000')
'Zs'
>>> unicodedata.category(u'\ufeff')
'Cf'
>>> unicodedata.category(u'\u0009')
'Cc'

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'