2012年7月28日
awkの代わりにperlを使おう
perlのコマンドラインオプションには-aってのがあります。これはawkモードです。perl --help見るとautosplit modeとか書いてありますが。
perlは-pや-nオプションを渡す事によってファイルを一行づつ処理してくれますが、その時に-aオプションを渡すと@F配列にフィールドの情報を自動的に入れてくれます。
フィールドのセパレータはデフォルトではスペースですが、-Fオプションで指定可能です。
カンマ区切りのテキストの、最初のフィールドだけを表示したい場合は以下の様な感じ。
% cat test.txt
server1,1343363124,30,/video.php
server2,1343363110,20,/profile.php
server3,1343363115,7,/login.php
server1,1343363105,8,/profile.php
% perl -aF, -nE 'say$F[0]' test.txt
server1
server2
server3
server1
awkでは$1,$2..にフィールドが入りますが、perlでは$F[0],$F[1]...に入ります。
行毎の処理をperlの文法で書けるので、僕はawk使わないでperl使うことにしています。僕がシェル力が足りないのもあって、なるべくperlでやりたい派。
てことで以下の問にも答えてみます。現実的に自分がやりそうな方法と、無理やりperlワンライナーやった方法を載せます。自分がperlでしかやらないなーってのはperlの方法だけ。
http://d.hatena.ne.jp/Yamashiro0217/20120727/1343371036
問1
% cat test.txt
% perl -pe '' test.txt
問2
% perl -aF, -pe '$_="$F[0],$F[3]"' test.txt
問3
% cat test.txt | grep ^server4
% perl -ne '/^server4/&&print' test.txt
問4
% cat test.txt | wc -l
% perl -ne 'eof&&print$.' test.txt
問5
% cat test.txt | sort -t',' -k1,1 -k3,3n | head -5
% perl -e 'print for map{join ",",@$_}sort{$a->[0]cmp$b->[0]||$a->[2]<=>$b->[2]}map{[split /,/, $_]}<>;' test.txt
問6
% cat test.txt | sort | uniq | wc -l
% perl -nE '!$m{$_}++&&$n++;eof&&say$n' test.txt
問7
% cat test.txt | cut -f3 -d, | sort | uniq | wc -l
% perl -aF, -nE '!$m{$F[2]}++&&$n++;eof&&say$n' test.txt
問8
% cat test.txt | cut -f4 -d, | sort | uniq -c | sort -nr | head -1
% perl -aF, -nle '$m{$F[3]}++;eof&&print join" ",@{(sort{$b->[0]<=>$a->[0]}map{[$m{$_},$_]}keys%m)[0]}' test.txt
問9
% perl -aF, -ple '$_=$F[0];s/server/xxx/' test.txt | sort | uniq -c
% perl -aF, -nlE '$_=$F[0];s/server/xxx/;$m{$_}++;eof&&say for map{"$m{$_} $_"}sort keys%m' test.txt
問10
% perl -aF, -nlE '$F[2]>9&&say$F[2]' test.txt | sort -n | uniq
% perl -aF, -nlE '$F[2]>9&&$m{$F[2]}++;eof&&say for sort keys%m' test.txt