blog.鶯梭庵

二〇〇七年 師走 十九日 水曜日

Perl で Jcode を使わずに日本語を扱う [/this_blog/perl]

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 で書くことができる。


use encoding 'EUC-JP';

$language = "日本語";

print length $language; # -> 3

$language =~ s/^../英/;

print $language; # -> 英語


encoding を使うことで何が起こるかというと、スクリプトファイル内にハードコードされた文字列や標準入力からの入力が、自動的にバイト列から Unicode のキャラクター列へと変換され、Perl の内部形式へとデコードされる。そして、標準出力に出力するときには、自動的にバイト列へとエンコードされる。(ちなみに、入力と出力に異なる文字コードを指定することもできるので、ファイルを読み込んでそのまま出力するだけで文字コードの変換をすることができる。)

しかし、CGI などでユーザから入力を受け付けるときは、これではうまくない。ユーザが、こちらが指定した文字コードで入力してくれると前提するわけにはゆかないからだ。ユーザからの入力は決して信用しないというのが、アプリケーションを作るときの大原則である。

そこでどうするか考えてみた。まず、入力時の自動デコードを停止して、入力をバイト列として受け取る。そして、入力されたバイト列が、こちらが期待する文字コードでエンコードされているかどうかを判定する。本来は Encode::Guess を使うのだろうが、以前にも書いたようにこれはあまり当てにならないので、文字コードを指定してとにかくデコードを試みる。Encode::decode に3つ目の引き数 1 を与えることによって、デコードができなかった場合にエラーが発生する。


use CGI ':cgi';

use Encode 'decode';

use encoding 'EUC-JP', STDIN => undef;

$string = eval { decode('EUC-JP', param('name'), 1) };

if ( $@ ) {

# エラー処理

} else {

# 入力値チェック

}


UTF-8 を使う場合は、次のようにも書ける。utf8 プラグマは、ハードコードされた文字列をデコードするが、入出力は変更しない。そこで、binmode を使って標準出力だけをエンコードしてやる。


use CGI ':cgi';

use Encode 'decode';

use utf8;

binmode STDOUT, ':utf8';

$string = eval { decode('UTF-8', param('name'), 1) };

... 以下同じ

[この記事にコメントを書く。] [このカテゴリをまとめて読む。] [最新の記事を読む。]

RSS feed

最近のツイート

カテゴリ

[/language] (73)
[/links] (205)
[/mac] (97)
[/music] (36)
[/origami] (374)
[/this_blog/ajax] (7)
[/this_blog/blosxom] (4)
[/this_blog/history] (12)
[/this_blog/perl] (9)

最新記事

検察の「暴走」・その1 [/links]
Weekend Japanology に出演 [/origami]
算数における掛け算について [/links]
「折り紙公理」の形式化・その6 [/origami]
「折り紙公理」の形式化・その5 [/origami]
折り紙ティーセット [/origami]
「折り紙公理」の形式化・その4 [/origami]
「折り紙公理」の形式化・その3 [/origami]
ジョセフ・ウーさんのインスタレーション [/origami]
「折り紙公理」の形式化・その2 [/origami]
「折り紙公理」の形式化・その1 [/origami]
Ear-igami [/origami]
ファスナー [/language]
ハーフカットと折り紙 [/origami]
吉澤展開催中 [/origami]

羽鳥 公士郎