2008年05月08日 04:00 [Edit]

perl - Encode 中級

camel

以前書いた

は大好評でしたが、

ウェブで利用される文字コード、UnicodeがASCIIを上回る--グーグルが明らかに:マーケティング - CNET Japan
Unicodeが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_HTMLCREFEncode::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:

追記:

ウェブで利用される文字コード、UnicodeがASCIIを上回る--グーグルが明らかに:マーケティング - CNET Japan
ASCIIと比べたときのUnicodeの短所としては、ローマ字を格納するのに2倍のメモリ容量を必要とする点が上げられる。これはUnicodeがより多くの文字記号に対応するため、文字をより多くのバイト数で表現するためである。

これはウソ。UTF-8はASCIIとは完全上位互換なので、内部処理はとにかく、外部表現のために必要なメモリーは変わりません。これはEUC-JPやShift_JISも同様。むしろUTF-8の場合、ほとんどの漢字が表現に2 bytesではなく3 bytes必要になる点の方がEUC-JPやShift_JISに対する欠点となるでしょう(正確にはs/byte/octet/g)。


この記事へのトラックバックURL

この記事へのトラックバック
Perlのバージョンが5になるかならないかの頃に作った送信フォームPerlスクリプトを「そろそろいい加減UTF-8化しないとなぁ」と思って、use CGI すらしていなかった(古っ!)シロモノだったので殆ど抜本的に作り直していて、、、「まぁ、こんなもんか(取り敢えず)」というとこ
formデータの取り出し時 Encode.pm を使ったちょっとした工夫【物語り研究所「夢前案内人」】at 2012年05月07日 03:13
Perlのバージョンが5になるかならないかの頃に作った送信フォームPerlスクリプトを「そろそろいい加減UTF-8化しないとなぁ」と思って、use CGI すらしていなかった(古っ!)シロモノだったので殆ど抜本的に作り直していて、、、「まぁ、こんなもんか(取り敢えず)」というとこ
formデータの取り出し時 Encode.pm を使ったちょっとした工夫【物語り研究所「夢前案内人」】at 2012年05月07日 03:13
404 Blog Not Found:perl - Encode 中級
404 Blog Not Found:perl - Encode 中級【】at 2012年02月22日 19:01
ブログの編集画面から投稿されたテキストデータは、ブログの表示画面ではHTMLという約束事でブラウザにより表示されています。文字だけ送信したにも関わらず画像が表示されるのは此の約束事によっています。このHTMLと云うものはホームページ(WEBサイト)を表示抔する際の約
HTMLエンティティ??ブログからもう一歩【ホームページ作成浜松Tips】at 2008年05月21日 08:00