二〇〇七年 師走 十九日 水曜日■ Perl で Jcode を使わずに日本語を扱う [/this_blog/perl]この記事は書かれてから1年以上経過しています。内容が古くなっている可能性があります。コメントの受付は終了しました。 Perl で日本語を扱う場合、ソースを EUC-JP または UTF-8 で書いて Jcode を使うというのが一般的だが、バージョン 5.8.1 以降であれば、Perl は実用に十分な程度に Unicode に対応しているので、Jcode を使う必要がない。 普通に $language = "日本語"; と書いた場合、あるいは外部から文字列を読み込んだ場合、Perl はこれをバイト(オクテット)の列として扱う。ソースが EUC-JP でエンコードされていれば 0xC6 0xFC 0xCB 0xDC 0xB8 0xEC だし、UTF-8 でエンコードされていれば 0xE6 0x97 0xA5 0xE6 0x9C 0xAC 0xE8 0xAA 0x9E だ。そのため、print length $language; と書いたら、EUC-JP の場合は 6 と出力されるし、UTF-8 なら 9 と出力される。 しかし、encoding プラグマを使うことで、Perl は文字列を正しく文字(キャラクター)の列として扱うようになる。たとえば、以下のソースを EUC-JP で書くことができる。
encoding を使うことで何が起こるかというと、スクリプトファイル内にハードコードされた文字列や標準入力からの入力が、自動的にバイト列から Unicode のキャラクター列へと変換され、Perl の内部形式へとデコードされる。そして、標準出力に出力するときには、自動的にバイト列へとエンコードされる。(ちなみに、入力と出力に異なる文字コードを指定することもできるので、ファイルを読み込んでそのまま出力するだけで文字コードの変換をすることができる。) しかし、CGI などでユーザから入力を受け付けるときは、これではうまくない。ユーザが、こちらが指定した文字コードで入力してくれると前提するわけにはゆかないからだ。ユーザからの入力は決して信用しないというのが、アプリケーションを作るときの大原則である。 そこでどうするか考えてみた。まず、入力時の自動デコードを停止して、入力をバイト列として受け取る。そして、入力されたバイト列が、こちらが期待する文字コードでエンコードされているかどうかを判定する。本来は Encode::Guess を使うのだろうが、以前にも書いたようにこれはあまり当てにならないので、文字コードを指定してとにかくデコードを試みる。Encode::decode に3つ目の引き数 1 を与えることによって、デコードができなかった場合にエラーが発生する。
UTF-8 を使う場合は、次のようにも書ける。utf8 プラグマは、ハードコードされた文字列をデコードするが、入出力は変更しない。そこで、binmode を使って標準出力だけをエンコードしてやる。
|
カテゴリ
[/language] (98) 最新記事
◇ パスワードについてのあなたの常識はもはや非常識かもしれない・その1 [/links] |