追記 完全版
↑のコードだと不完全ですよう、とトラックバックを頂いたので、実際業務で使ったコード(の該当ロジック部分を抜粋)を晒しておきます。入力文字コードのチェックが厳密になっています。あと、splitを12でlimitしたことで更に40%位(うろ覚え)早いです。
リファラのデコードに対応していないのも惜しい。
は全てのリファラの元の文字コードを正確に判別るするのは非常にコストが高く、精度も出ないので止めた覚えが。膨大なログを処理する必要があったので、端折ったような気がします。
リファラがある場合とない場合とで検索語のフィールドが変わるから
の部分はよく分からなかった(リファラがあるから検索語があるような。。)のですが、まー大体これでいけますよ。
#!/usr/bin/perl use strict; use warnings; use URI::Escape::XS qw/ uri_unescape /; use Encode qw//; use Encode::Guess qw/ eucjp shiftjis utf8 /; my $out_enc = Encode::find_encoding("eucjp"); my $in_encs = { utf8 => Encode::find_encoding("utf8"), eucjp => Encode::find_encoding("eucjp"), shiftjis => Encode::find_encoding("shiftjis"), }; while ( my $line = <> ) { chomp $line; my @items = split " ", $line, 12; $items[10] = convert($items[10]) if $items[10] =~ /\?/; print join " ", @items; print "\n"; } exit; sub convert { my $referer = shift; $referer = uri_unescape($referer); return $referer if $referer =~ /^[\x00-\x7f]*$/sx; # is ascii my $in_enc = ( $referer =~ /=utf[-_]?8/isx )? $in_encs->{utf8} : ( $referer =~ /=euc[-_]?jp/isx )? $in_encs->{eucjp} : ( $referer =~ /=shift[-_]?jis/isx )? $in_encs->{shiftjis} : ( $referer =~ /google\./isx )? $in_encs->{utf8} : Encode::Guess->guess($referer); return ref $in_enc? $out_enc->encode( $in_enc->decode($referer) ) : $referer; # could not guess } __END__