YAMAGUCHI::weblog

海水パンツとゴーグルで、巨万の富を築きました。カリブの怪物、フリーアルバイター瞳です。

文字列処理のモジュールを使ってのUnicode処理もろもろ

はじめに

こんばんは、Python界の情弱王子です。Erlang界の貴公子 id:kuenishi とはエライ違いですね。さて、昨日Pythonを使ってちょっとしたCSVデータの処理をしていたときに、正規表現モジュールではまったことがあったのでここにメモしておきます。

参考

いつも心に公式ドキュメント。今回は諸事情につきPython 2.6でのお話。

空白の扱い

複数の半角/全角スペースでの分割

普通に空白文字での区切りの場合(たとえば全角文字1文字)だったら、stringモジュールのsplitでいいと思うんです。この場合、デフォルトでは空白文字(連続含む)があればなんでも切ってしまいます。

>>> for s in string.split(u"すぱむ  えっぐ はむ"):
...   print s
... 
すぱむ
えっぐ
はむ

しかし、正規表現が必要になる場合のsplit、特にUnicodeを扱うときは若干はまりました。re.match()などはre.UNICODEのフラグを直接受け付けられるのですが、re.split()はフラグを受け付けられません。この場合はre.compile()してからsplit()する戦略にするようです。

>>> for s in re.compile(u"\s+", re.UNICODE).split(u"すぱむ  えっぐ はむ"):
...   print s
... 
すぱむ
えっぐ
はむ

Python 2.7ではキーワード引数flagで正規表現のフラグを受け付けてくれます。
ここでre.split()だけでやってしまうとre.UNICODEフラグを渡した時のように、LOCALEに合わせて良きに計らってくれないので期待した動作はしてくれません。(ascii文字のみ)

>>> for s in re.split(u"\s+", u"すぱむ  えっぐ はむ"):
...   print s
... 
すぱむ  えっぐ
はむ
ascii文字のみかどうかの判定

先日、Unicode文字列の中身が半角英数字を含むかどうかを判定する必要があり、こんな関数を書きました。

def __has_english(self, unicode_str):
    """
    if unicode_str is consisted with only single byte characters,
    then this returns True. 

    unicode_str - unicode string
    """
    return False if re.match(ur"[\w\s]+", unicode_str) is None else True

ここでは、先程のsplitで起きた期待していない状況を逆に使って、ascii文字がなければmatchしないようにしています。しかし日本語だけ含む場合にTrueにしたい場合にはどうしたらいいかなあと考えてて困ってました。これ以外にもっとスマートで分かりやすいコードがあればぜひ教えてください。

謝辞

このエントリは id:moriyoshi, id:atsuoishimoto のご協力によりリリースしております。おかげで仕事が進みました!あざす!