2008年02月18日 10:00 [Edit]
perl - utf8::is_utf8("\x{ff}") == 0
ちょうどいい機会なので、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
Posted by dankogai at 10:00│Comments(3)│TrackBack(1)
この記事へのトラックバックURL
この記事へのトラックバック
unknownplace.org - 2008/02/17 404 Blog Not Found:perl - utf8::is_utf8("¥x{ff}") == 0 弾さんの書いてるのはもちろん間違いではないのだが、ちょっと今回はなしていたのとはポイントが違っていて、 な
utf8::is_utf8 considered harmful【Bulknews::Subtech】at 2008年02月18日 14:33
この記事へのコメント
どうでもいいことだけれど、コードの中では flag ではなく frag としているのは、意図してなのかタイポなのかが気になる。前者なら、さらにその意図が気になるし、後者なら、dankogai でも L と R を混同することがあるのか気になる。ほんとにどうでもいいことだけれど。
Posted by N at 2008年02月18日 15:39
洋楽歌詞検索 http://www.lovecms.com
Posted by 洋楽 at 2008年02月18日 15:58
Nさん、
というわけで"utf8flag"に統一しました。
ちなみにfragというのはfragmentの略として使われていて、私も使っています。
Dan the Typo Generator
というわけで"utf8flag"に統一しました。
ちなみにfragというのはfragmentの略として使われていて、私も使っています。
Dan the Typo Generator
Posted by 弾 at 2008年02月18日 16:20