省略が行き過ぎたPerlはfor(‘P’,’e’,’r’,’l’){print;}で終わり

スクリプト言語では最強勢力ではないかと思っている、Perl、
なんかことあるごとにPerl言ってる割にはPerlをいままで使ったことがなくてねぇ。
Perlでできることというといろいろあるけど、やはり文字列処理に強いです。
それとやっぱりスクリプト言語らしく、変数の書き方なんかがおもしろい。
特に省略の仕方が怖すぎる。

#!/usr/bin/perl
open (IF,"<$ARGV[0]");
open (OF,"|terapad");
while(<IF>){
$_ =~ s/\s+$//;
s/^\s+//;
print OF "$_\n";
}
close (IF);
close (OF);

1行目はインタプリンタのパス。だいたい/usr/bin/perlみたいだね。
さて、ファイルの読み込み方がすごくて、リダイレクトとかみたいな書き方をする。<だから読み込み専用。
>foo.txtなら白紙にして書き込み(w)、>>foo.txtなら追加(a)てな感じ。
さらに不思議なのはパイプからもらったり、パイプに渡したり出来る。今回はTerapadに渡すことを考える。
@ARGVは引数。0から引数本体。
Perlの配列は@fooとか表すのだが、$n番目の内容は$foo[$n]と表す。
連想配列もあって、%barと表すのだが、キーが$hogeの内容は$bar{$hoge}となるわけだな。
ところで連想配列って、いろいろ訳があって、ハッシュテーブルとかいろいろだな。まぁここではもっぱら連想配列と言うが。
次のwhileなのだが、どうも慣れない。
イメージ的にはこんな感じ。

while(!eof(IF)){
$_ = <IF>;
#中身
}

という感じ。この<IF>というやつはファイルポインタを囲んでるだけなのだが、
$foo=<IF>;とすると1行読み込み、@foo=<IF>とすると配列にファイルを読み込み、
if(<IF>)とするとEOFに到達してないかという非常にマルチなやつで、
whileでは1行読み込みと同時にEOFにならないか確認している。while($foo=<IF>)のようにかくと$fooに読み込まれるのだが、
これも省略すると、$_に読み込まれる。なでしこに「それ」というのがあるが、これはきっと$_を模したものだろう。
=~という演算子は、置換やらそういうことをするための演算子で、置換はs/(正規表現)/(置換後)/の要領で書く。
まぁこの置き換えはおもしろくなくて、行の最後の1つ以上の連続した空白、最初の1つ以上の連続した空白をそれぞれ無に置換するというもの。
しかし、$_ =~ s/^\s+//;とあれば、単にs/^\s+//;とかくだけでいい。
ファイルへの書き込みはprint OF "$_\n";のように、ファイルポインタと書きたいものを空白でつなぐだけ。
ファイルポインタがSTDOUTなら省略できる、書きたいことが$_ならば、省略できる。
こんな風な省略というものはやまほどあって、
ファイルポインタ関係なら、<>と書けば<STDIN>のことだし、さっき言ったとおりprint "hoge";と書けば、書き出し先はSTDOUT。

#!/usr/bin/perl
open(IF,"<$ARGV[0]");
@foo = <IF>;
$len=@foo;
print "$len\n";
foreach(@foo){
s/\s+$//;
foreach( split(/,/) ){ print "$_ | "; }
print "\n";
}
close(FP);

さっき言ったとおり、@foo=<IF>とすると配列に読み込めると。
さて、ここで$len=@fooと代入して、それを表示させたが2と出る。配列の要素の数だな。
これを使ってforでループを作って配列を回すのもありなのだが、今回はforeachを使った。
foreach(@foo)とすると、@fooの中身を1つづつ$_に出して、処理できる。
$_じゃなくて$barにしたければforeach $bar(@foo)と書く。
foreachは建前上順序は不定だが、まぁこの際いいことにしよう。だいたい順序通りだし。
まず、行の最後の空白を取り除いて、sprit(/,/,$_)を考える。$_はあえて省略した。
これは配列だから、@barに代入してもいいんだが、これをそのままforeachで回してもらう。
で、"$_ | "を表示すると。こんな風に変数が展開されるのはPerlのいいところです。PHPも同様だが。
ダブルクオーテーションで囲めばこんな風に取り扱われる。
$fooの後にooという文字をつけるとき、"$foooo"とすると問題があるのは自明だから、"${foo}oo"と書ける。
あと、Perlはifなどの後が1文でも{ }で囲まないといけない。
ところでforeachの()内に入れるのは、配列、連想配列。
その一方、配列を自動作成するすばらしいものがあって(0..$len-1)と書くと、0,1,…,$len-1という配列をつくってくれると。
だから、増分が1のforループはforeachで連続した配列を回してやればできると。

foreach(0..9) {print "$_\n";}

もちろんforループはCなどで見慣れたあの形式だから、普通に使える。
あと、比較演算子なんだが、文字とそれ以外で異なる。

foreach(0..9){
if($_ < 3) {print "小\n";} elsif($_==3) {print "等\n"; } else {print "大\n"; }
}
foreach("山内","山田","山本"){
if($_ eq "山本") {print "一致\n";} else {print "異\n"; }
}

文字の比較演算子はアルファベットというわけです。なかなかおもしろいな。
なかなか強力だ。
しかし、残念なのは、Windowsマシンには標準で入ってないことだ。
本当に残念。Linuxでは間違えなく入ってて、sh並みに間違えなく使える物なのに。
家のマシンではCygwinのPerlで、部のマシンではActivePerlでやってます。
Perlを使って具体的に何ができるんだというと、それはちょっと答えにくいけど、
テキストファイルを大量に処理するには非常にいい。
ファイルリストをSTDINから読み込んで、それぞれ開いて、置換などを施して、保存してということとかね。
さっきのような狂った省略を使うことで、ずいぶんと作りやすくなるだろうね。
あと、タイトルにもあるような短いスクリプトはもっと簡単に、

$ perl -e "for('P','e','r','l'){print;}"

とすれば動くよ。
この気楽さもPerlの売りです。
あ、そうそう、foreachの代わりにforを使ってもいいらしいよ。文字数減らすためにタイトルはfor使ってる。
けどわかりにくくなるのでforeachを使おうな。