2008年02月18日 10:00 [Edit]

perl - utf8::is_utf8("\x{ff}") == 0

camel

ちょうどいい機会なので、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


この記事へのトラックバック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
Posted by at 2008年02月18日 16:20