変態的に書きたいときはこんなカンジでw
perl -pe '$\=$_}{' hoge.log最終行だけ表示するPerlワンライナー - すぎゃーんメモ
ちょっと何書いてるのか理解できないですね(汗
% perl -le 'print for(1..10)' > hoge.log % cat hoge.log 1 2 3 4 5 6 7 8 9 10 % perl -pe '$\=$_}{' hoge.log 10
おぉ。ちゃんと動く。
全く理解できんので、スクリプト化してみる。
% perl -MO=Deparse -pe '$\=$_}{' hoge.log LINE: while (defined($_ = <ARGV>)) { $\ = $_; } { (); } continue { die "-p destination: $!\n" unless print $_; } -e syntax OK
一行ずつ読込んだ内容($_)をレコードセパレータ($\)にして、その後はよくわからん。。。
指先一つPerl一行野郎でダウンさ〜(俺が)
Perl のスローガン
There's more than one way to do it
を肌で感じた。
追記:
力を全部読み終わるまで"$\ = $_;"が繰り返され上書きされ続け、最終的に最後の行だけが$\に入ります。
変態的な Perl ワンライナー - ablog
あとは最後に一度だけ"print $_"が呼ばれますが、この時点では$_はundefになっていて、代わりに$\(出力レコードセパレータなのでprint文の後に必ず出力される)だけが出力されることになります。
$\でない他の変数を使おうとすると
perl -pe '$a=$_}{$_=$a' hoge.log
というカンジでしょうか。TIMTOWTDIこわいですね ><
id:sugyan さんからコメントいただいちゃった。
ありがとうございます!
この時点では$_はundefになっていて、代わりに$\(出力レコードセパレータなのでprint文の後に必ず出力される)だけが出力されることになります。
なるほど。頭いいっすね!
あとは最後に一度だけ"print $_"が呼ばれますが、この時点では$_はundefになっていて、
これがなんでかわからない。
そもそも
perl -pe '$\=$_}{' hoge.log
の「}{」がなんなのかわからない。
スクリプト化すると、
{ (); }
となっている。なんじゃこれ?
プログラミングPerl〈VOLUME1〉
P. 143
4.5 裸のブロック
BLOCK単体(ラベルはあってもなくてもよい)は、意味的には、1回だけ実行されるループと等価である。
ってことは、乱暴に言うと
$i=0; while ($i<1) { $i=1; }
みたいな感じか。
あと、continue { ... } ってなんだろ?
ミニマルPerl ―Unix/LinuxユーザのためのPerl習得法
P.348
ループの次の繰り返しの前に実行すべきコードを中に含むcontinueブロックを付けることができます。
ふむふむ。
ループ {();} をはさんで、$_ をクリアしてから print $_; するから、レコードセパレータのみ表示されるってことか。
厳密には違うところがあると思うけど、自分のようなサルでわかるコードにしてみた。
% cat hoge1.pl open (IN, "< $ARGV[0]"); while (<IN>) { $\ = $_; } continue { print $_; } close(IN); % perl hoge1.pl hoge.log 1 1 ... 10 10
となっちゃうからループをはさんでやると、
% cat hoge2.pl open (IN, "< $ARGV[0]"); while (<IN>) { $\ = $_; } $i=0; while ($i<1) { $i=1; } continue { print $_; } close(IN); % perl hoge2.pl hoge.log 10
最終行のみ表示される。
}{ と書いたらなんで、{();} になるのかについてはわからなかった><
追記(2009/08/28):
UNIXのtailコマンドじゃダメ?
最終行だけ表示するPerlワンライナー - すぎゃーんメモ
tail -n 1 hoge.log
最終行を表示するだけなら tail で良いのですが、もう少し複雑なことをしたかったので Perl を使いました。具体的に以下のようなことをしました。
% perl -wne 'if($.==2){$a=substr($_,0,12)}elsif(eof){$b=substr($_,0,12);print substr($ARGV,3,7) . " $a $b\n";close ARGV}' hoge<1-500>.log