キーワード

プロフィール

深沢千尋

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

最新記事

最新コメント

最新トラックバック

月別アーカイブ

カテゴリ

検索フォーム

RSSリンクの表示

リンク

ブロとも申請フォーム

QRコード

QRコード

スポンサーサイト

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

「まるごとEncode」解題(7)ファイル処理

17日の沈黙を経て続き。
沈黙中に実のあるコメントとトラックバックをいただいているが、それもおいおい研究します。

以下は、これまで学んだ基礎を踏襲して、ファイル処理を行う。
基礎は以下の通り。

(1)外界から読み込んだオクテットストリームを decode して Perl 文字列にする
(2)Perl 文字列を処理する
(3)Perl 文字列を encode してオクテットストリームに変えて外界に書き出す

では以下のプログラムを実行してみよう。

#! perl
# decodeEncodeFile.pl -- ファイルの読み込み、置換、出力

use strict;
use warnings;
use utf8;
use Encode;

for my $argv (@ARGV) {
open my $fh, "<", $argv or die "cannot open $argv because $!";
while (<$fh>) {
my $utf8 = decode("shiftjis", $_);
$utf8 =~ s{ (?:深沢|ふかざわ|フカザワ)
[\s\x{3000}]* # \s + FULLWIDTH SPACE
(?:千尋|ちひろ|チヒロ)
} {Perl Describer}gmsx;
print encode("eucjp", $utf8);
}
}
__END__

実行する前にプログラムを解説する。

@ARGV はプログラムの引数を受け取る配列だ。
この1個1個を $argv に入れながら for ループを回している。
$argv を入力ファイル名として開き、ファイルハンドル $fh に関連付けている。
open が失敗したら or 以降が実行され「ファイル $argv は理由 $! によって開けません」と言って die している。
open に成功したらファイルハンドル $fh を逐次読み込みしている。

入力した各行 $_ を Shift_JIS 文字コードで解釈して decode し、得られた Perl 文字列を $utf8 に入れている★ここがミソ1

次に、$utf8 を s/// で置換している。
ここでは
 深沢千尋
 ふかざわ(全角空白2個)チヒロ
 フカザワ(半角空白2個とタブ3個)ちひろ
などの「深沢千尋っぽい文字列」を「Perl Describer」という文字列に置換している。

・s{from}{to} 形式でカッコを使って分かりやすく文字列を指定していること。
・(?:aaa|bbb|ccc)はaaaまたはbbbまたはccc、(?:~)は文字列を捕獲しないグルーピング
・\x{XXXX}(XXXXは16進数)で Unicode スカラー値 U+3000 の文字(全角空白)をあらわしていること★ここがミソ2
・s/// 演算子の x 修飾子によって正規表現内の空白、改行、注釈を有効化する(perlre によると「Use extended regular expressions.」だそう。http://perldoc.perl.org/perlop.html#Regexp-Quote-Like-Operators)

などに注目したい。

さて、最後に $utf8 の中身を、EUC-JP 文字コードで解釈して encode し、得られたオクテットストリームを print 出力している★ここがミソ3

print は標準出力に関連付けられているので、標準出力に処理された全行がズラズラ~と連続表示される。

★ミソ1:decode

my $utf8 = decode("shiftjis", $_);
入力した各行 $_ を Shift_JIS 文字コードで解釈して decode し、得られた Perl 文字列を $utf8 に入れている★ここがミソ1

これはいいだろう。
Shift_JIS のことを shiftjis と書いているが、これは「だいたい」合っていれば使える。
このことは後で出てくるので後続記事を「だいたい」で検索のこと。

★ミソ2:\x{XXXX}

[\s\x{3000}]* # \s + FULLWIDTH SPACE
・\x{XXXX}(XXXXは16進数)で Unicode スカラー値 U+3000 の文字(全角空白)をあらわしていること★ここがミソ2

\x{XXXX} は Unicode 文字1文字を表す。
(perluniintro で解説されている http://perldoc.jp/docs/perl/5.8.1/perluniintro.pod)

ちょっと気になることがあるので試してみる。

#! perl
# naniwanoJoe.pl -- 辰吉丈一郎の名前を正しく書いてみる

use strict;
use warnings;
use utf8;
binmode STDOUT, ':encoding(cp932)'; # 出力はCP932に変更

print "辰吉丈一郎のジョウは正しくは\x{2000B}だというが、さて、出せるか?\n";

__END__

テスト。

F:\Dropbox20091029\My Dropbox\Marugoto\test>naniwanoJoe.pl
"\x{2000b}" does not map to cp932 at F:\Dropbox20091029\My Dropbox\Marugoto\test\naniwanoJoe.pl line 9.
辰吉丈一郎のジョウは正しくは\x{2000b}だというが、さて、出せるか?

\x{2000b}が cp932 にないから出せない、ということだ。
じゃあ UTF-8 だったら出せるとでも?(戸田奈津子調?)

#! perl
# naniwanoJoe.pl -- 辰吉丈一郎の名前を正しく書いてみる

use strict;
use warnings;
use utf8;
#binmode STDOUT, ':encoding(cp932)'; # 出力はCP932に変更

print "辰吉丈一郎のジョウは正しくは\x{2000B}だというが、さて、出せるか?\n";

__END__

テスト。

F:\Dropbox20091029\My Dropbox\Marugoto\test>naniwanoJoe.pl > k.txt
Wide character in print at F:\Dropbox20091029\My Dropbox\Marugoto\test\naniwanoJoe.pl line 9.

F:\Dropbox20091029\My Dropbox\Marugoto\test>

怒られたな。
こうするか。

#! perl
# naniwanoJoe.pl -- 辰吉丈一郎の名前を正しく書いてみる

use strict;
use warnings;
use utf8;
binmode STDOUT, ':encoding(utf8)'; # 出力はUTF-8に変更

print "辰吉丈一郎のジョウは正しくは\x{2000B}だというが、さて、出せるか?\n";

__END__

テスト。

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

F:\Dropbox20091029\My Dropbox\Marugoto\test>

怒られなくなった。
では k.txt を見てみるか。

20091205joeWin.png

ダメだぁ。

では最近購入した Mac でこれを見てみる。

拡張子 .txt のファイルを何も考えないでダブルクリックするとテキストエディットというアプリで開こうとするが、これだとダメ。

20091205macTxtOpenError.png

だけど、CotEditorというので開いてみると、見事に開いて見え、正しいジョウの字が見られた。

20091205cotEditorJoe.png

U+2000B というのは、16進数5ケタであることからも分かるとおり、サロゲートペアである。
この時は Windows XP 上の MS ゴシックだとフォントがないようだ。
でも UTF-8 文字としては正しいコード(0xF0 A0 80 8B)が生成され、Mac 上ではフォントがあったのでちゃんと見られた。
では同じ Windows でも Vista だとどうだとか、XP でも Meiryo(メイリオ)を入れたらどうだとか、特に方針を決めずに書いているとドンドン話が逸れる。
とりあえずこの辺にしておこう。
\x{XXXX} の XXXX は Unicode スカラー値が入る。

★ミソ3:encode

print encode("eucjp", $utf8);
さて、最後に $utf8 の中身を、EUC-JP 文字コードで解釈して encode し、得られたオクテットストリームを print 出力している★ここがミソ3

ここではミソ1の逆で、$utf8 を EUC-JP でエンコードして出力。
ここでもいい加減な名前 eucjp を使っている。

ちなみに、この名前は IANA というところに登録しているのだが、正しい名前は Shift_JIS(Shift と JIS の間はアンダーバー)、EUC-JP(EUC と JP の間はハイフンマイナス)が正しいそうだ。

ではテストしてみる。
2個ファイルを Shift_JIS で用意。

love.txt- - - - - - ココカラ - - - - - - - - - - - - - - - - ->8
あなたはフカザワチヒロだ
お前こそが、ふかざわ   ちひろだね
キミハ深沢 千尋ダネ!
- - - - - - - - - - ココマデ - - - - - - - - - - - - - - - - ->8

kiss.txt- - - - - - ココカラ - - - - - - - - - - - - - - - - ->8
フカザワチヒロサンコンニチハ
ふかざわ   ちひろ さん こんにちは
深沢 千尋 様 今日は
- - - - - - - - - - ココマデ - - - - - - - - - - - - - - - - ->8

では実行。

F:\Dropbox20091029\My Dropbox\Marugoto\test>decodeEncodeFile.pl love.txt kiss.txt > e.txt

F:\Dropbox20091029\My Dropbox\Marugoto\test>

出力は euc なのでリダイレクトしてみた。
e.txt の中を見てみる。

20091205euc.png

出来てるっぽい。
ちなみに秀丸のステータスバーの日本語表示だが、
 日本語 (Shift-JIS)
 日本語(EUC)
と微妙にキモチワルイ。
「秀丸で SHift-JIS と書いているのは正しくは Shift_JIS のことだ」
とか教養にならない知識(これを非教養知識と呼ぼう)を増やしていかないといけないのだ。
ちなみに Microsoft のメモ帳がもっとすごくて「ANSI」なのである。

今回は横道が多かった。
スポンサーサイト

<< 「まるごとEncode」解題(8)ファイル処理(2) | ホーム | 「まるごとEncode」解題(6)そして encode() >>


コメント

コメントの投稿


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

 ホーム 


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