
すでにOSCONでもYAPCでも、あちこちそちこちでこの基本方針に関しては話したのですが、ここ 404 Blog Not Found でも改めて。
Perl で utf8 化けしたときにどうしたらいいか - TokuLog 改め だまってコードを書けよハゲ入り口で decode して、内部ではすべて flagged utf8 で扱い、出口で encode する。これがすべてです!とにかくこの基本方針をまもっていれば幸せになれます。
ここでは、EUC-JPでエンコードされたファイル中の「小飼弾」「こがいだん」「コガイダン」「Kogai Dan」を正規表現で書き換えて標準出力にEUC-JPで出力するプログラムを例にとって説明します。
decode() then encode()
まず、こちらが基本中の基本。
use strict; use utf8; use Encode; for my $argv (@ARGV){ open my $fh, "<", $argv or die "$argv : $!"; while(<$fh>){ my $utf8 = decode("eucjp", $_); $utf8 =~ s{ (?:小飼|こがい|コガイ|Kogai) [\s\x{3000}]* # \s + FULLWIDTH SPACE (?:弾|だん|ダン|Dan) }{Encode Maintainer}gmsx; print encode("eucjp", $utf8); } }
find_encoding()
くりかえしdecode()
とencode()
する場合には、OOインターフェースを使った方が高速です。なぜなら(de|en)code
が文字コード名を解決する手間がなくなるからです。
use strict; use utf8; use Encode; my $eucjp = find_encoding('eucjp'); for my $argv (@ARGV){ open my $fh, "<", $argv or die "$argv : $!"; while(<$fh>){ my $utf8 = $eucjp->decode($_); $utf8 =~ s{ (?:小飼|こがい|コガイ|Kogai) [\s\x{3000}]* # \s + FULLWIDTH SPACE (?:弾|だん|ダン|Dan) }{Encode Maintainer}gmsx; print $eucjp->encode($utf8); } }
PerlIO and open()
ファイルをopen()
する段階で、文字コードを指定することもできます。以下の例では、入力の際にdecode
を済ませています。
use strict;
use utf8;
use Encode;
for my $argv (@ARGV){
open my $fh, "<:encoding(eucjp)", $argv or die "$argv : $!";
while(<$fh>){
s{ (?:小飼|こがい|コガイ|Kogai)
[\s\x{3000}]* # \s + FULLWIDTH SPACE
(?:弾|だん|ダン|Dan)
}{空気嫁}gmsx;
print encode("eucjp", $_);
}
}
binmode()
さらにbinmode
を使うと、すでに開いているファイルハンドルの文字コードを変更することも可能です。use Encode;
しなくても動いている点に留意してください。
use strict;
use utf8;
# use Encode;
binmode STDOUT, ":encoding(eucjp)";
for my $argv (@ARGV){
open my $fh, "<:encoding(eucjp)", $argv or die "$argv : $!";
while(<$fh>){
s{ (?:小飼|こがい|コガイ|Kogai)
[\s\x{3000}]* # \s + FULLWIDTH SPACE
(?:弾|だん|ダン|Dan)
}{404 Replacement Not Found}gmsx;
print;
}
}
まとめ
Encodeには他にもうんざりするほどいろいろな機能がありますが、上記の基本で日常業務の9割5分はカヴァーされているかと思います。「decodeしていじってencode」、この基本をお忘れなく。
Dan the Encode Maintainer
See Also:
- http://www.dan.co.jp/~dankogai/yapcasia2006/slide.html
- 「まるごとPerl! Vol. 1」まるごとEncode by 小飼弾
nilさん>OK把握。
お目汚し失礼しました…… (to 弾さん&閲覧者各位)