RssRollingを作っていていつも悩まされていたのが Perl における Unicode 文字列の文字化け。ちょっと調べてみました。
なお、Perl の Unicode サポートについては貞廣知行さんの'Perlのページ - PerlのUnicode support'にとても詳細に記述されており、とても助かりました。
さて、Perl はバージョン 5.6 以降、Unicode をサポートしています。「サポート」とは具体的にどういうことなんでしょうか。Unicode はマルチバイトの文字コードですが、そのマルチバイトを(利用者の意図する)「文字単位」で扱うことができたりするというのが簡単な説明になるかと思います。「あ」というマルチバイト文字があったときに、それを1文字として扱える、ということです。
#!/usr/local/bin/perl use utf8; my $string = "あいうえお"; print length($string), "\n";
このスクリプトの出力は「5」になります。(スクリプト自体は UTF-8 で記述します。) 文字がバイト単位ではなく、文字単位で数えられている証拠です。(utf8 プラグマは、スクリプトの文字コードを UTF-8 で記述するときに利用します。これによって、スクリプトに直接記述されたマルチバイト文字列に UTF8フラグが立ちます。UTF8フラグについては後述。)
場合によっては、文字単位ではなくバイト単位で扱いたいときもあります。そんなときのために、Perl は Unicode 文字列に内部的なフラグ - UTF8フラグを設けて、それを基準に対象の文字列データをUnicode文字単位で扱うか、バイト単位で扱うかを場合分けします。
例えば Perl の XML パーサの代表的な実装である XML::Parser は、入力された XML 文書を内部で UTF-8 にエンコードします (正確には UCS-2 に変換され、内部コードとして UTF-8 にエンコードされる、とのこと。'Manabu Higashida's Technical Laboratory Coverting UTF-8' より)。このときに UTF8フラグが立ちます。XML のパースに XML::Parser を使っているXML::RSS などで RSS 文書を処理すると、UTF8フラグが立った文字列として結果が返ってきます。
例えば
#!/usr/local/bin/perl
use strict;
use warnings;
use XML::RSS;
use LWP::Simple;
 
my $rss = XML::RSS->new;
$rss->parse( get('http://naoya.dyndns.org/~naoya/mt/index.rdf') );
my $title = $rss->{items}->[0]->{title};
 
printf("%s\n%d\n", $title, length($title));
 
utf8::encode($title);
printf("%d\n", length($title));
というスクリプトを実行してみます。
[naoya@mary Unicode]$ ./rssutf8.pl | nkf -e Wide character in print at ./rssutf8.pl line 11. 小沢健二『刹那』はまだ先のようです 17 51
RSSから一件目の記事のタイトルを抜き出して、その文字列の長さを数えます。(警告が出てい