blog.鶯梭庵

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

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


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] (98)
[/links] (254)
[/mac] (114)
[/music] (36)
[/origami] (406)
[/this_blog/ajax] (7)
[/this_blog/blosxom] (4)
[/this_blog/history] (12)
[/this_blog/perl] (9)

最新記事

パスワードについてのあなたの常識はもはや非常識かもしれない・その1 [/links]
ニューラルネットワークとディープラーニングで翻訳はどうなる・その5 [/language]
ニューラルネットワークとディープラーニングで翻訳はどうなる・その4 [/language]
HTTPS 対応 [/links]
ひらがな・カタカナ学習ウェブアプリ [/links]
日本語の「た」と英語の過去形 [/language]
ORI-REVO で回転楕円体を折る・その2 [/origami]
ORI-REVO で回転楕円体を折る・その1 [/origami]
折り紙建築 [/origami]
折鶴に松図小柄 [/origami]
改訂版・たぶん、ほとんどの人は viewport meta タグの指定をまちがえてる・その6 [/links]
改訂版・たぶん、ほとんどの人は viewport meta タグの指定をまちがえてる・その5 [/links]
改訂版・たぶん、ほとんどの人は viewport meta タグの指定をまちがえてる・その4 [/links]
改訂版・たぶん、ほとんどの人は viewport meta タグの指定をまちがえてる・その3 [/links]
改訂版・たぶん、ほとんどの人は viewport meta タグの指定をまちがえてる・その2 [/links]

羽鳥 公士郎