2008年05月08日 04:00 [Edit]
perl - Encode 中級
以前書いた
は大好評でしたが、
ウェブで利用される文字コード、UnicodeがASCIIを上回る--グーグルが明らかに:マーケティング - CNET JapanUnicodeがASCIIを追い越し、World Wide Web上で最も多く利用されている文字コード体系になったとGoogleのシニアインターナショナルソフトウェアアーキテクトMark Davis氏がブログで述べている。
という時代に完全対応するには、入門以上の知識がちょっと必要になります。
例えば、本blogをホストしてくれているlivedoor blogの文字コードはEUC-JP。「時代はUnicode」だと言っても、こうした事情もまだ残っています。それでは、例えばEUC-JPやShift_JISを使っているCGMで、Unicodeの文字を扱うことは出来ないのでしょうか☹
そんなことは、もちろんありません☺
EUC-JPやShift_JISで扱えない文字も、HTMLやXMLではCharacter Reference (文字参照;CREF)という方法で表記することが可能です。例えば、☺は☺または☺と表記すればいいのです。前者はその文字のUnicodeを10進数表記、後者は16進表記したものです。
しかし、往年の区点コードじゃあるまいし実際にこうしたことを手でやるのはあまりに面倒。そこで、Encodeの出番となります。
三番目の引数
例えば、「UTF-8で書かれたTextをEUC-JPに変換し、変換しきれないものは実体参照に」するには、以下のとおりとします。
use Encode;
while(<>){
my $utf8 = decode_utf8($_);
print encode('eucjp', $utf8, Encode::FB_HTMLCREF);
}
Encode::FB_HTMLCREFはEncode::FB_XMLCREFでも構いません。10進数表記が16進数表記になるだけです。
また、これの代わりにEncode::FB_PERLQQを使うと、変換しきれないものをPerlの\x{XXXX}表記にすることも出来ます。
% perl -CIO -MEncode -nle 'print encode("ascii", $_, Encode::FB_PERLQQ)'
小飼弾 (Dan Kogai)
\x{5c0f}\x{98fc}\x{5f3e} (Dan Kogai)
もともと、この3番目の引数は、変換エラーを検知するためのものでした。例えばこんな感じです。
% perl -CIO -MEncode -nle 'print encode("ascii", $_, 1)'
小飼弾 (Dan Kogai)
"\x{5c0f}" does not map to ascii at /usr/local/lib/perl5/5.10.0/darwin-thread-multi-2level/Encode.pm line 146, <> line 1.
しかし、単にエラーを検知するだけではなく、エラーの場合には別の処理もできるようになっています。
定数でなくクロージャーを渡す
さらにEncode 2.12からは、定数を渡してそれに応じた処理をさせるだけではなく、クロージャーを渡してユーザー独自の処理もできるように改善されました。例えば最初の例は、以下のように書き直すことも可能です。
use Encode;
while(<>){
my $utf8 = decode_utf8($_);
print encode('eucjp', $utf8, sub{ sprintf "&#%d;", $_[0] });
# sub{ sprintf "&#%x;", $_[0] } # FB_XMLCREF
# sub{ sprintf "\\x{%x};", $_[0] } # FB_PERLQQ
}
見ての通り、クロージャーに渡す最初の引数が、EUC-JPに変換できない文字のordとなります。
まとめ
decode()およびencode()では、三番目の引数を指定できますdecode_utf8()およびencode_utf8()では二番目の引数に相当します
- 指定することにより、変換できない文字をどう扱うかをカスタマイズすることができます
さらにEncodeには文字コードをユーザー定義する機能までありますが、これはさすがに上級編ということで、書くとしたら別entryということになるでしょう。
Dan the Encode Maintainer
See Also:
- http://www.dan.co.jp/~dankogai/yapcasia2006/slide.html
- 「まるごとPerl! Vol. 1」まるごとEncode by 小飼弾
追記:
ウェブで利用される文字コード、UnicodeがASCIIを上回る--グーグルが明らかに:マーケティング - CNET JapanASCIIと比べたときのUnicodeの短所としては、ローマ字を格納するのに2倍のメモリ容量を必要とする点が上げられる。これはUnicodeがより多くの文字記号に対応するため、文字をより多くのバイト数で表現するためである。
これはウソ。UTF-8はASCIIとは完全上位互換なので、内部処理はとにかく、外部表現のために必要なメモリーは変わりません。これはEUC-JPやShift_JISも同様。むしろUTF-8の場合、ほとんどの漢字が表現に2 bytesではなく3 bytes必要になる点の方がEUC-JPやShift_JISに対する欠点となるでしょう(正確にはs/byte/octet/g)。


