perl 5.8.2

そろそろ多国語対応が安定してきたっぽい。
以下はソースをutf8で書いていてcp932の端末で動かして確認。

標準入出力の多国語対応

use utf8;
binmode($_,":encoding(cp932)") for STDIN ,STDOUT ,STDERR;
print STDERR "何か一行入力して:";
$input = ;
print STDOUT "入力したのは $input\n";

別の書き方。encodingモジュールはSTDERRには効かない。

use utf8;
use encoding 'utf8',STDIN=>'cp932',STDOUT=>'cp932';
binmode(STDERR,":encoding(cp932)");
print STDERR "何か一行入力して:";
$input = ;
print STDOUT "入力したのは $input\n";

まずい例

use encoding 'utf8';
binmode(STDIN ,":encoding(cp932)");

use encoding 'utf8',STDIN=>'cp932';
binmode(STDIN ,":encoding(cp932)");

たとえ同じ文字コードを指定しても、二重に変換しておかしなことになるようだ。STDOUTも同様。

ソースコード中の日本語

use encoding; ではリテラル内部が多国語化される。
use utf8; は変数や関数の名前も多国語化できる。

use utf8;
binmode($_,":encoding(cp932)") for STDIN ,STDOUT ,STDERR;
$変数 = 'てすと';
print "$変数\n";
$変数 =~ s/す/正規表現/;
print "$変数\n";
$perlにハァハァした人の数 =int rand 100000000;
print "perlにハァハァした人の数→${perlにハァハァした人の数}人\n";
sub 日本語の関数{ print "日本語の関数名もおっけー\n"; }
日本語の関数();

まずい例:山カッコ演算子は多国語化されていない。

open(IN,"<:encoding(shift_jis)","cp932.txt")or die $!;
print ;
open(my $ファイルハンドル,"<:encoding(cp932)","cp932.txt")or die $!;
print <*$ファイルハンドル>;
open(日本語のファイルハンドル,"<:encoding(cp932)","cp932.txt")or die $!;
print <日本語のファイルハンドル>;

は以下を出力するか、もしくは出力時にエンコードに失敗する。

(ファイルの中味)
GLOB(0x1a9513c)
日本語のファイルハンドル

ファイルハンドル自体は使えるので以下はうまく動く。

open(ファイルハンドル,"<:encoding(cp932)","cp932.txt")or die $!;
use IO::Handle; 
print ファイルハンドル->getlines;

文字コードの自動判別

use utf8;
binmode($_,":encoding(cp932)") for STDIN ,STDOUT ,STDERR;
use open IO => ":bytes";  my $bytes = join( undef, <> );
use Encode::Guess; my $enc = guess_encoding( $bytes, qw/ cp932 euc-jp 7bit-jis / );
ref $enc or die "文字コード判別に失敗: $enc\n";
warn "encoding=",$enc->name,"\n";
use Encode;   print decode($enc->name,$bytes),"\n";

<> の文字コード

perlには 引数に指定したファイル全ての中味もしくは標準入力を読む <> と があるのだが、このファイルハンドルにエンコーディングを指定する方法は use open IN=>':encoding(cp932)'; しかない。http://www.lr.pi.titech.ac.jp/~abekawa/perl/perl_unicode.html が詳しい。

use open ARGV=> ...; とか書けると幸せなんだがな。