unpack()メモ1
perlpacktutを読んでる途中で覚えたことメモ。
以下のようなテキストファイルの処理を考える。
Date |Description | Income|Expenditure 01/28/2001 Flea spray 24.99 01/29/2001 Camel rides to tourists 235.00
僕も多分にもれず、文字数決まってるならsubstrでちまちまやればいいのかな、と思った。
while (<>) { my $date = substr($_, 0, 11); my $desc = substr($_, 12, 27); my $income = substr($_, 40, 7); my $expend = substr($_, 52, 7); ... }
まあ確かに何文字目から何文字というのをいちいち完璧に数える必要はあるなー。
とここでunpack()の出番。
いままで僕はほとんど自力では使ったことがなかった。
unpack()にわたすのは、変換用のテンプレートと変換元文字。
そうそう、このテンプレートに気後れというか何か大きな壁のようなものを感じていたのだ。
では、unpack()を使った実例。
while (<>) { my ($date, $desc, $income, $expend) = unpack("A10xA27xA7A*", $_); ... }
いままで、この第一引数に"H*"とか"C"とか入れられてるのしか見たことがない(と思う)けど、こう書かれるとその意味がなんとなくわかる。
そして実際その直感は正しい。
つまり、"A10", "x", "A27", "x", "A7", "A*" という要素にこれは分解できて、それぞれが第二引数の変換元文字と照らし合わされる。
(まあ結局は何文字分か、というのは数えなくてはだめらしい)
"A" は "ASCII" のこと。
"x" は スペースかと思ったけど、「1バイト読み飛ばす」という意味(pack()だと「NULL byte」)。
最後の "*" は、正規表現なんかと同じで、あってもなくてもというやつか("if there’s anything left, take it")。
収入だけの行には支出の項目がないから、「あと12文字」という指定は clever じゃない。
このテンプレートに合わせて切り出して配列で返してくれる。
つづく。