{ブロック}の外でのみ use utf8; したいのだが・・・
連投申し訳ありません。
「まるごとPerl」(2006年9月、インプレス刊)という本の「まるごとEncode」という記事に従ってEncodeの勉強をしています。
原記事は UNIX(というか端末コードをUTF-8に出来る環境)ですが、それをWindowsに移植しようとして苦労しています。
#! perl
# list3 -- UTF-8モードとバイトモードの切り替え
# インデントを表現するために全角空白を使っています
use strict;
use warnings;
binmode STDOUT, ':encoding(cp932)'; # 追加
# ブロックの外側ではUTF-8文字単位で解釈される
use utf8;
{
# ブロックの外側ではバイトモードが強制される
use bytes;
my $text = '漢字、カタカナ、ひらがなの混じったtext';
print Encode::decode('UTF-8', substr($text, 9, 12)); # カタカナと表示されたい
}
my $text = '漢字、カタカナ、ひらがなの混じったtext';
print substr($text, 3, 4); # カタカナと表示されたい
__END__
というプログラムを実行すると
C:\>list3.pl
カタカナカタカナ
と表示されてほしいのですが、
C:\>list3.pl
Cannot decode string with wide characters at C:/strawberry/perl/lib/Encode.pm li
ne 174.
と表示されます。
use utf8 を後ろにズラして
#! perl
# list3 -- UTF-8モードとバイトモードの切り替え
# インデントを表現するために全角空白を使っています
use strict;
use warnings;
binmode STDOUT, ':encoding(cp932)'; # 追加
{
# ブロックの外側ではバイトモードが強制される
use bytes;
my $text = '漢字、カタカナ、ひらがなの混じったtext';
print Encode::decode('UTF-8', substr($text, 9, 12)); # カタカナと表示されたい
}
# ブロックの外側ではUTF-8文字単位で解釈される
use utf8; # 移動
my $text = '漢字、カタカナ、ひらがなの混じったtext';
print substr($text, 3, 4); # カタカナと表示されたい
__END__
とするとうまく動いて
C:\>list3.pl
カタカナカタカナ
と表示されます。
#! perl
# list3 -- UTF-8モードとバイトモードの切り替え
# インデントを表現するために全角空白を使っています
use strict;
use warnings;
binmode STDOUT, ':encoding(cp932)'; # 追加
# ブロックの外側ではUTF-8文字単位で解釈される
use utf8;
my $text = '漢字、カタカナ、ひらがなの混じったtext'; # 移動
print substr($text, 3, 4); # カタカナと表示されたい # 移動
{
# ブロックの外側ではバイトモードが強制される
use bytes;
my $text = '漢字、カタカナ、ひらがなの混じったtext';
print Encode::decode('UTF-8', substr($text, 9, 12)); # カタカナと表示されたい
}
__END__
のようにするとやはり最初と同じエラーになりますが、
#! perl
# list3 -- UTF-8モードとバイトモードの切り替え
# インデントを表現するために全角空白を使っています
use strict;
use warnings;
binmode STDOUT, ':encoding(cp932)'; # 追加
# ブロックの外側ではUTF-8文字単位で解釈される
use utf8;
my $text = '漢字、カタカナ、ひらがなの混じったtext'; # 移動
print substr($text, 3, 4); # カタカナと表示されたい # 移動
no utf8; # 追加
{
# ブロックの外側ではバイトモードが強制される
use bytes;
my $text = '漢字、カタカナ、ひらがなの混じったtext';
print Encode::decode('UTF-8', substr($text, 9, 12)); # カタカナと表示されたい
}
__END__
だと大丈夫です。
結果として、ブロックの外で use utf8;、中では use bytes; という記事の著者の意図通りに動作しないようで、ブロックの中まで use utf8; が効いているようです・・・。
これは Perl の実装が変わったのでしょうか。
使用しているのは Windows XP Home SP3+Strawberry Perl v5.10.0 です。
お礼
皆さんありがとうございました。 私の技量では解決できそうも無いので、encoding を使わない(文字コードを使う)方法で解決しました。