
ちょうどいい機会なので、Perl 5.8以降におけるutf8フラグの立ち方を。
unknownplace.org - 2008/02/17 - utf8::is_utf8ということで、"\x{6751}\x{702c}\x{5927}\x{8f14}" などというData::Dumper表記でかならずしも utf-8フラグがたつわけじゃない。ということがいいたかったんだと思うのだけれど、
\x{UUUUUU}とutf8 flag
まずはクイズです。以下がどう出力されるかを答えなさい。
sub pfrag{ print utf8::is_utf8($_[0]) ? 1 : 0, "\n" } pfrag "Hell\xC3, world!"; pfrag "Hell\x{C3}, world!"; pfrag "Hell\x{FFC3}, world!";
答えは、「0,0,1と一行ずつ出力される」です。これはuse utf8
プラグマとは関係なく常にそうなります。
それでは、Perlはどこを見てフラグを切り替えているのでしょう?\x{UUUUUU}
の中身です。UUUUUUが、0x100以上の場合のものが一つでも含まれていればフラグを立て、そうでなければ立てません。
直書きとutf8 flag
それでは、以下の場合はどうでしょうか。
sub pfrag{ print utf8::is_utf8($_[0]) ? 1 : 0, "\n" } no utf8; { use utf8; pfrag "弾"; pfrag "\x{c3}弾"; } { pfrag "弾"; pfrag "\x{c3}弾"; }
答えは、「1,1,0,0と一行ずつ出力される」です。この場合、use utf8
プラグマの有無が振るまいを変えます。
以上をpseudocodeでまとめると、以下のとおりとなります。
if (引用符の中に(エスケープも含めて)ascii以外の文字が入っている?){ utf8flag = utf8プラグマ; }else{ if (引用符の中に\x{}や\N{}などのエスケープが含まれている){ utf8flag = ord(\x{}) >= 0x100 が含まれている? 1 : 0; } else{ utf8flag = 0; } }
なぜこうなっているかといえば、下位互換性。"Perlの文字リテラルはISO-LATIN-1である"という旧来の常識で書かれたコードがあまりに多かったのでこういう形になりました。
問答無用にutf8フラグを立てる
それでは、問答無用にutf8フラグを立てるにはどうしたらよいでしょうか。今のところの公式の推奨は
use Encode; my $utf8 = decode_utf8($unknown);
となります。Perl 5.8.1からは
utf8::decode($unknown);
も使えるようになりましたが、しかし後者の場合は引数が定数の場合は使えません。フラグの変更も書き込みに相当するからです。前者の方がベタープラクティスです。その逆、問答無用でフラグを落とすには、
use Encode; my $bytes = encode_utf8($unknown);
とします。
Dan the Encode Maintainer
というわけで"utf8flag"に統一しました。
ちなみにfragというのはfragmentの略として使われていて、私も使っています。
Dan the Typo Generator