・Unicode
最近,python で遊んでいることもあって,Unicode/UTF-8 へのアレルギーが多 少は改善されてきた感じ.
例えば,以下は最近書いた Windows の cp932 で作ったファイル名を euc-jp に変換する Python のスクリプトの一部.手元ではローマ数字を使ったファイ ル名にぶつかることがあるのだけど,ローマ数字は euc-jp の世界には存在し なくて,nkf のレベルだとうまく変換してくれないので,Unicode な世界で英 数字に変換してから euc-jp にするような感じにしてみた.
def check_roman(s): table = ( (u'\u2160' , u'I'), (u'\u2161' , u'II'), (u'\u2162' , u'III'), (u'\u2163' , u'IV'), (u'\u2164' , u'V'), (u'\u2165' , u'VI'), (u'\u2166' , u'VII'), (u'\u2167' , u'VIII'), (u'\u2168' , u'IX'), (u'\u2169' , u'X'), (u'\u216A' , u'XI'), (u'\u216B' , u'XII'), (u'\u216C' , u'L'), (u'\u216D' , u'C'), (u'\u216E' , u'D'), (u'\u216F' , u'M'), (u'\u2170' , u'i'), (u'\u2171' , u'ii'), (u'\u2172' , u'iii'), (u'\u2173' , u'iv'), (u'\u2174' , u'v'), (u'\u2175' , u'vi'), (u'\u2176' , u'vii'), (u'\u2177' , u'viii'), (u'\u2178' , u'ix'), (u'\u2179' , u'x'), (u'\u217A' , u'xi'), (u'\u217B' , u'xii'), (u'\u217C' , u'l'), (u'\u217D' , u'c'), (u'\u217E' , u'd'), (u'\u217F' , u'm'), (u'\u2180' , u'1000'), (u'\u2181' , u'5000'), (u'\u2182' , u'10000'), (u'\u2183' , u'r100'), (u'\uff5e' , u'〜') ) new_str = '' for i in s[:]: match = False for j in table: if i.find(j[0]) >= 0: new_str = new_str + j[1] match = True break if match == False: new_str = new_str + i return new_str files = os.listdir('.') for i in files: utf_name = i.decode('cp932') new_name = check_roman(utf_name) os.rename(i, new_name.encode('euc-jp'))
Python の場合,不変なオブジェクトと可変なオブジェクトがあって,文字列は 不変なオブジェクトだから,既存の文字列を置換するのではなく,新しいオブ ジェクトに一文字ずつチェックしながらコピーするような形にしているのだけ ど,unicode な文字列だと,バイト列みたいに 1バイト目や 2 バイト目といっ た条件を気にしなくていいので処理は楽な感じ.
あと,Python の場合は内部 Unicode なので,外部から取ってきた文字列は, 外部の文字コードを指定して Unicode に decode してやり,外部に出す時はそ れぞれの文字コードに encode してやる,というのもちょっと最初は戸惑った のだけど,「Python チュートリアル」の付録で鴨澤さんが書いてた
Pythonの(というか元々の意味での)「Unicode 文字列」とは,「世界中の文字が全 部入った抽象オブジェクト(文字集合)」である.この大元の抽象オブジェクトから, 個々のエンコーディング(codec)に「エンコード」してやると,現実世界で表示や書 き出しが可能な状態になるのだ.一方「デコード」とは,文字の現実世界でのかりそ めの表現を,「魂の集積所」である Unicode 空間に解き放ってやることである.
という(「エヴァンゲリオン」を思わせるような :-)表現でよく理解できた.
で,この Unicode 空間を Unix なファイル名とぶつからないように投影したの が UTF-8 だ,と考えると(euc-jp ほど,日本語を簡潔できれいには表現できな くても) 悪くはないかなぁ,,という気がしてきた(笑
(u'\u2460' , u'(1)'), (u'\u2461' , u'(2)'), (u'\u2462' , u'(3)'), (u'\u2463' , u'(4)'), (u'\u2464' , u'(5)'), (u'\u2465' , u'(6)'), (u'\u2466' , u'(7)'), (u'\u2467' , u'(8)'), (u'\u2468' , u'(9)')kojima 2008-04-01 (火) 22:12:18
def check_roman(s): table = { u'\u2160':u'I', u'\u2161':u'II', u'\u2162':u'III', .... u'\u2468':u'(9)' } L=[] for i in table.keys(): L.append(i) new_str = '' for i in s[:]: if i in L: new_str = new_str + table[i] else: new_str = new_str + i return new_str
たぶん、こっちの方が効率もよさそう -- kojima 2008-04-07 (月) 09:16:35