camel

すでに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: