キーワード

プロフィール

深沢千尋

Author:深沢千尋
みなさんこんにちは、深沢千尋です。(公式ページ
文字コード【超】研究 改訂第2版NEW!」「すぐわかるPerl」「すぐわかる オブジェクト指向 Perl」の著者です。
ここでは、多くは技術的でないこと、ごくまれに技術的なことをなげやりに書いていきます。
メールは suguwakaruPerl@gmail.com まで。(アットマークは ASCII に)
Twitterはじめました。@query1000です。よろしく~

最新記事

最新コメント

最新トラックバック

月別アーカイブ

カテゴリ

検索フォーム

RSSリンクの表示

リンク

ブロとも申請フォーム

QRコード

QRコード

スポンサーサイト

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

「まるごとEncode」解題(6)そして encode()

つづき。

以下のプログラムがあるとする。

#! perl
# noBinmode.pl -- decode して encode しないと怒られる
use strict;
use warnings;
use Encode;

my $utf8 = decode_utf8('abc漢字ひらがなカタカナ');
my $substr = substr($utf8, 5, 4);

print $substr;

__END__

実行してみる。(UTF-8 出力されるからリダイレクトで)

F:\Dropbox20091029\My Dropbox\Marugoto>noBinmode.pl > k.txt
Wide character in print at F:\Dropbox20091029\My Dropbox\Marugoto\noBinmode.pl line 12.

k.txt には正しく

ひらがな

と入っているが、「ワイド文字を print しました」と怒られる。
これは、既出だが、Perl 内部表現の文字列をオクテットストリームに変換しないでそのまま print したときのエラーである。
この場合は、binmode を使うか、Encode::decode_utf8() の逆関数 Encode::encode_utf8() を使う。

ここでは、encode_utf8(); を使ってみる。

#! perl
# expEncode.pl -- encode の実験
use strict;
use warnings;
use Encode;

my $utf8 = decode_utf8('abc漢字ひらがなカタカナ');
my $substr = encode_utf8(substr($utf8, 5, 4));

print $substr;

__END__

実行。

F:\Dropbox20091029\My Dropbox\Marugoto>expEncode.pl > k.txt

エラーが消えた。

無論、encode('UTF-8', ...) としても一緒である。

#! perl
# expEncode.pl -- encode の実験
use strict;
use warnings;
use Encode;

my $utf8 = decode_utf8('abc漢字ひらがなカタカナ');
my $substr = substr($utf8, 5, 4);

print encode("UTF-8", $substr);

__END__

今度はリダイレクトしないで実行してみると

F:\Dropbox20091029\My Dropbox\Marugoto>expEncode.pl
ゅ・繧峨′縺ェ

昔は文字化けというと魚偏だったけど、最近はこの糸偏が多い。
UTF-8 文字を強制的に Shift_JIS で解釈するとこのように怒られる。
ここで "UTF-8" を好みの文字コードに変えられる。

#! perl
# expEncode.pl -- encode の実験
use strict;
use warnings;
use Encode;

my $utf8 = decode_utf8('abc漢字ひらがなカタカナ');
my $substr = substr($utf8, 5, 4);

print encode("cp932", $substr);

__END__

F:\Dropbox20091029\My Dropbox\Marugoto>expEncode.pl
ひらがな

CP932 なので正しく DOS 窓に表示された。



さて、少し横道に逸れるが、現在スクリプトは UTF-8 になっているので、スクリプトに UTF-8 にはあるけれど、CP932 の文字レパートリーにない難しい字を書いた時にどうなるのかという問題がある。

#! perl
# expEncode.pl -- encode の実験
use strict;
use warnings;
use Encode;

#my $utf8 = decode_utf8('abc漢字ひらがなカタカナ');
my $utf8 = decode_utf8('abc漢字♠♥♦♣カタカナ');
my $substr = substr($utf8, 5, 4);

print encode("cp932", $substr);

__END__

いま、「ひらがな」の変わりに「♠♥♦♣」というトランプのマークを書いた。
これは、U+2660 らへんからある Unicode 文字である。

20091112tramps.png

CP932 にあるかどうか知らない。
試みにこのスクリプトを秀丸で言うところの「日本語(Shift-JIS)」で保存してみる。
(IANA 登録名は Shift-JISではなくて Shift_JIS であり、実際には DOS 窓のコードページは CP932 だが)
次のように怒られる。

20091112henkanErr.png

[はい] をクリックするとこうなる。

20091112hatena.png


あららー。
元通り、♠♥♦♣に直して、UTF-8で保存しておく。

20091112resaved.png

では実行する。

F:\Dropbox20091029\My Dropbox\Marugoto>expEncode.pl
????

? になって表示された。

これ、昨日 Dan Kogai さんじきじきに教わったのだが、encode に第3引数として 1 を渡せばよいという。

こうだ。

#! perl
# expEncode.pl -- encode の実験
use strict;
use warnings;
use Encode;

#my $utf8 = decode_utf8('abc漢字ひらがなカタカナ');
my $utf8 = decode_utf8('abc漢字♠♥♦♣カタカナ');
my $substr = substr($utf8, 5, 4);

print encode("cp932", $substr, 1);

__END__

実行する。

F:\Dropbox20091029\My Dropbox\Marugoto>expEncode.pl
"\x{2660}" does not map to cp932 at C:/strawberry/perl/lib/Encode.pm line 158.

あらホントだ~。
U+2660 は上に見たとおり確かにスペードである。

以下は参考ページ。
・http://blog.livedoor.jp/dankogai/archives/51047005.html

encode の第3引数については「まるごと」でも述べられており、よって本記事でも後述する。



ということで、基本はこう。

・処理の前に decode() -- オクテットストリームを Perl内部表現にする
・文字単位で処理
・処理の後に encode() -- Perl内部表現をオクテットストリームにする

「この基本を覚えておけば、Encodeの使い方はマスターしたも同然です。」(原記事より)



さて、また上の記事に戻るが、やはり CP932 でスクリプトを書きたい人は存在するだろう。
この場合は use utf8; の代わりに use encodings "cp932"; と書けるのだが、これは Dan さんによって強く非推奨されている。

・http://blog.livedoor.jp/dankogai/archives/50857509.html
・http://blog.livedoor.jp/dankogai/archives/51221731.html

表示の表やソ連のソの後半に \5c が入っていて、Perl は他にも @ とかいろいろぶつかるから、プログラムは EUC-JP で書いて入出力は nkf をかます、とか昔から言ってたのだが、今はプログラムは UTF-8 で書いて use utf8; し、外部からの入力は decode、外部への出力は encode するというのが正しいあり方のよう。

ただ、これに問題があるのが、Windows で使うプログラムを UTF-8 で書くと CP932 にない漢字(♠♥♦♣)を書いちゃうのではないか、ということなのだが、Dan さんによると、encode の第3引数に 1 を渡すと、croak してくれるという。
これは上でも見たがすごく便利。

でも、
 ・プログラムを書いた瞬間に怒られたい気がする
   <=これは何らかのハックで、CP932 チェッカー的なものを保存時に走らせればいいだけかも。
Emacs とかだったらカンタンにできるのだが・・・。

 ・encode ではなくて binmode でできないだろうか?
   <=とりあえず binmode に第3引数が「ない」ことは確かのよう。
これは今後の研究課題

今回は以上。
スポンサーサイト

<< 「まるごとEncode」解題(7)ファイル処理 | ホーム | 「まるごとEncode」解題(5)今さら decode() の解説されても・・・ >>


コメント

拙作ですが、コマンドプロンプトに直接flagged utf8文字列を渡せるモジュールを開発してます。(♠♥♦♣も表示できます)
まだalphaレベルですが、よろしければ試してみてください。
http://github.com/xaicron/p5-win32-unicode

P.S.
自分は深沢さんの著書、「すぐわかる オブジェクト指向 Perl」でPerlのオブジェクト指向を勉強しました。
今、Perlが好きで、毎日書いているのも、この本を読んだからだと思っています。
最高におもしろくて、わかりやすかったです。

どもども!

xaicronさんお世話になります。
コメントはずいぶん前に把握してたんですが、さいきんマックを買ったもので、すっかりそっちに時間を取られてしまい、お返事を忘れてしまいました。
拙著がお役に立ち、あっという間に著者を追い抜いてりっぱなモジュールを開発されているようで望外の喜びです。
ぜひ使わせていただき、研究させていただきますのでよろしくお願いします。
今後もよろしく!

コメントの投稿


管理者にだけ表示を許可する

トラックバック


この記事にトラックバックする(FC2ブログユーザー)


はじめてのAcme

ぶたときどき真珠~深沢千尋のブログ~ 「まるごとEncode」解題(6)そして encode() これに問題があるのが、Windows で使うプログラムを UTF-8 で書くと CP932 にない漢字(&#9824;&#9829;&#9830;&#9827;)を書いちゃうのではないか、ということなのだが、 (...中略)


 ホーム 


上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。