diary/Kojima

・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 ほど,日本語を簡潔できれいには表現できな くても) 悪くはないかなぁ,,という気がしてきた(笑

 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



トップ   編集 凍結 差分 バックアップ 添付 複製 名前変更 リロード   新規 一覧 検索 最終更新   ヘルプ   最終更新のRSS
Last-modified: 2021-12-17 (金) 16:35:41