2008年04月09日 01:00 [Edit]
perl - Encode 入門
すでに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 小飼弾
Posted by dankogai at 01:00│Comments(8)│TrackBack(4)
この記事へのトラックバックURL
この記事へのトラックバック
以前書いた
404 Blog Not Found:perl - Encode 入門
は大好評でしたが、
ウェブで利用される文字コード、UnicodeがASCIIを上回る--グーグルが明らかに:マーケティング - CNET JapanUnicodeがASCIIを追い越し、World Wide Web上で最も多く利用されている文字コー...
perl - Encode 中級【404 Blog Not Found】at 2008年05月08日 04:10
何年も前から使っている自分フレームワーク(というか自分モジュール集?)があるのだ...
最近Perlスクリプトを書いていて愕然とすること【日曜プログラマのそゞろ事】at 2008年07月24日 00:20
良記事。
第7回■文字エンコーディングが生み出すぜい弱性を知る:ITpro
だけど、問題点のみ具体例があって、対策にないのが片手落ちに感じられたので、その点を補足。
perl - EncodeでXSSを防ぐ【404 Blog Not Found】at 2009年03月03日 18:59
404 Blog Not Found:perl - Encode 入門
404 Blog Not Found:perl - Encode 入門【】at 2012年01月24日 22:14
この記事へのコメント
encodingに「:」が足りません…
Posted by H.I. at 2008年04月09日 08:45
と、思ったら少なくとも5.10では:encoding()でもencoding()でも動きますね…いつからだろう?
Posted by H.I. at 2008年04月09日 15:29
コード中にUTF8以外の文字コード(ex. EUC-JP)で文字列を書くときの
use encoding "EUC-JP"; # use utf8; の代わりに
も紹介しておくと良いかと。
use encoding "EUC-JP"; # use utf8; の代わりに
も紹介しておくと良いかと。
Posted by Yuichirou at 2008年04月09日 18:22
H.Iさん、
念のために、というよりperlioがstackableであることを示すために:を追加しました。
Yuichirouさん、
use encoding はどちらかというと deprecate したいプラグマなので。
Dan the Perl Monger
念のために、というよりperlioがstackableであることを示すために:を追加しました。
Yuichirouさん、
use encoding はどちらかというと deprecate したいプラグマなので。
Dan the Perl Monger
Posted by 弾 at 2008年04月09日 20:53
> use encoding はどちらかというと deprecate したいプラグマなので。
へぇ……なぜ deprecate(非難する、反対する)するのか気になりますが、だとすれば、やはりソース中の文字列も decode 関数に通す、つまり基本同様「decodeしていじってencode」とすべきなのですね。
へぇ……なぜ deprecate(非難する、反対する)するのか気になりますが、だとすれば、やはりソース中の文字列も decode 関数に通す、つまり基本同様「decodeしていじってencode」とすべきなのですね。
Posted by Yuichirou at 2008年04月09日 21:15
この場合、depricate は「非推奨」のほうの意味では?
Posted by keita at 2008年04月10日 08:44
たとえば
http://www.kt.rim.or.jp/~kbk/zakkicho/zakkicho16.html#D20061003-1
http://www.kt.rim.or.jp/~kbk/zakkicho/zakkicho16.html#D20061003-1
Posted by nil at 2008年04月10日 14:59
keitaさん>そうだった、"deprecated"=「非推奨」。忘れてました。
nilさん>OK把握。
お目汚し失礼しました…… (to 弾さん&閲覧者各位)
nilさん>OK把握。
お目汚し失礼しました…… (to 弾さん&閲覧者各位)
Posted by Yuichirou at 2008年04月11日 18:33
