考えてみると当たり前なんだけど、毎回考えるのが面倒なので動くコードをまとめておく。
Perlはunicode周りの挙動が面倒なんだよなあ。Python(3)の方がシンプルでよいね。モダンな言語はやっぱりこの辺の取り扱いがスマートだわ。
YAML::Syck
UTF-8 エンコーディングの差異まとめ YAML::XS、YAML::Syck、YAML::Old、YAML、YAML::Tiny - Tociyuki::Diary
普通の用途としてはLoadFile/DumpFileでファイルI/Oをする時に使うだけでしょう。
$YAML::Syck::ImplicitUnicode = 1 を指定すると、Load/Dumpの際にutf-8 decode/encodeをしてくれるようになります。
use strict; use warnings; use utf8; binmode STDOUT, ":utf8"; use YAML::Syck; $YAML::Syck::ImplicitUnicode = 1; my $names = LoadFile(shift); my $keyword = 'ネコプラ'; foreach my $n (@$names){ printf("%s %s $keyword\n", $n, (($n =~ /$keyword/) ? 'is' : 'is not')); }
$ perl a.pl data.yaml 立花りく_//ネコプラ// is ネコプラ 坂下雅_なんキニ! is not ネコプラ 成瀬かおり_//ネコプラ// is ネコプラ 双葉ゆり(ラルムーン) is not ネコプラ 大島遥華_KATA☆CHU is not ネコプラ 高宮さくら_//ネコプラ// is ネコプラ 藍川みり_//ネコプラ// is ネコプラ 佐藤まりん_chuLa is not ネコプラ もも is not ネコプラ
JSON::XS
[Perl] JSON モジュールの utf8 フラグ周りの仕様 tips 注意点: Kawanet Blog II
ややこしいですね。
JSON::XSは直接ファイルI/Oをしてくれるメソッドが用意されていないので、
- バイト列として読み込んでutf8(1)経由でデコード
- UTF-8文字列として読み込んでutf8(0)(デフォルト)でデコード
のどちらかで処理する必要があります。
use strict; use warnings; use utf8; binmode STDOUT, ":utf8"; use Path::Class qw/file/; use JSON::XS; my $content = file(shift)->slurp; my $names = JSON::XS->new->utf8->decode($content); # あるいはこちらでも可 # my $content = file(shift)->slurp(iomode => '<:encoding(utf-8)'); # my $names = JSON::XS->new->decode($content); my $keyword = 'ネコプラ'; foreach my $n (@$names){ printf("%s %s $keyword\n", $n, (($n =~ /$keyword/) ? 'is' : 'is not')); }
YAMLと違ってJSONはファイルだけでなくWeb APIでも使われることが多いので、JSON::XSには常にUTF-8 encode済みの文字列を渡す(utf8-flag disabledとして使う)という運用のほうが分かりやすいかもしれません。
まあ、「入口でdecode、出口でencode」の原則さえ分かっていればやりやすい方法でいいかなと思いますが。