2010-12-06
Perlによるワンライナー
ワンライナーを書くときに便利なオプション
-e オプション
続く文字列をワンライナーだと認識させる。シェルによる解釈を防ぐためにシングルクォートで囲む。
$ perl -e 'print "hello world\n"' hello world
-n オプション
プログラム全体をwhile(<>){...}で囲ったものと同じ効果が得られる。
$ perl -ne 'print "$_\n"' input.txt
は
while{<>}{ print "$_\n" }
を実行させたのと同じである。
-l オプション
出力に改行文字をつける。
$ perl -ne 'print "a \n"' input.txt
は
$ perl -nle 'print "a "' input.txt
-a オプション
@F=split(/ /,$_)と同じ意味。デフォルトの変数$_をスペースで区切って@Fに格納。awkのようなカラム処理をするときに必要。
$ perl -nle '@F=split(/ /,$_); print "$F[0]"' input.txt
は
$ perl -nlae 'print "$F[0]"' input.txt
と同じ意味。
-F オプション
デフォルトでは、-aオプションの区切り文字はスペースだが、それを変更したいときに使う。
$ cat input.txt 1,2,3 4,5,6 $ perl -F, -nlae 'print $F[0]' input.txt 1 4
ワンライナー20例
プログラム言語AWKに載っている"便利 な「一行野郎」たち"をperlに翻訳した。awkによる例とともに示す。
1. 入力行の総数を出力する
$ awk 'END{print NR}' input.txt
$ perl -nle 'END{print $.}' input.txt
awkでは行番号はNRに格納されているのに対し、perlでは$.に格納されている。
2. 10行目の入力行を出力する
$ awk 'NR == 10' input.txt
$ perl -nle 'if($. == 10){print }' input.txt
awkは'パターン{アクション}'という構文をとるのだが、アクションが入力行をそのまま出力する、つまり、{print $0}の場合は省略できるので、非常にシンプルに書ける。perlではprint文の対象が$_の場合、省略ですることができる。
3. すべての入力行の最後のカラムを出力する
$ awk '{print $NF}' input.txt
$ perl -nlae 'print $F[-1]' input.txt
awkではNFがカラム数を格納する変数なので、最後のカラムは$NFで参照できるのに対し、perlでは$F[-1]を使って参照している。
4. 最後の行の最後のカラムを出力する
$ awk '{f = $NF} END{print f}' input.txt
$ perl -nlae '$f = $F[-1]; END{print $f}' input.txt
5. カラム数が4を超える行を出力する
$ awk 'NF > 4' input.txt
$ perl -nlae 'if(@F > 4){print }' input.txt
6. 最後のカラムの値が4を超えるようなすべての行を出力する
$ awk '$NF > 4' input.txt
$ perl -nlae 'if($F[-1] > 4){print }' input.txt
7. すべての入力行のカラムの総数を出力する
$ awk '{c += NF}END{print c}' input.txt
$ perl -nlae '{$c += @F}END{print $c}' input.txt
perlでは配列をスカラコンテキストで評価すると要素数が返ってくる。
8. Bethを含む行の総数を出力する
$ awk '/Beth/{sum++}END{print sum}' input.txt
$ perl -nle 'if(/Beth/){$sum++}END{print $sum}' input.txt
9. 第一カラムが最も大きな行を出力する(第一カラムのうち少なくとも1つは正の数であると仮定)
$ awk '$1 > max{max = $1; ml = $0}END{print ml}' input.txt
$ perl -nlae 'if($F[0] > $ml[0]){@ml = @F}END{print "@ml"}' input.txt
10. 少なくとも1つのカラムをもつ行をすべて出力する
$ awk 'NF > 0' input.txt
$ perl -nlae 'if(@F > 0){print }' input.txt
11. 80文字以上の長さを持つ行をすべて出力する
$ awk 'length($0) >= 80)' input.txt
$ perl -nle 'if(length($_) >= 80){print }' input.txt
12. 行のカラム数とその行自体を出力する
$ awk '{print NF, $0}' input.txt
$ perl -nlae 'print scalar(@F)," $_"' input.txt
13. すべての行の最初の2つのカラムを逆順で出力する
$ awk '{print $2, $1}' input.txt
$ perl -nlae 'print "$F[1] $F[0]"' input.txt
14. すべての行の最初の2つのカラムを逆順にしてすべてのカラムを出力する
$ awk '{t = $1; $1 = $2; $2 = t; print }' input.txt
$ perl -nlae '($F[0], $F[1]) = ($F[1], $F[0]); print "@F"' input.txt
15. すべての行を最初のカラムを行番号に置き換えて出力する
$ awk '{$1 = NR; print }' input.txt
$ perl -nlae '$F[0]=$.; print "@F"' input.txt
16. すべての行の2つ目のカラムを消去して出力する
$ awk '{$2 = ""; print}' input.txt
$ perl -nlae 'splice(@F,1,1); print "@F"' input.txt
17. すべての行のカラムを逆順で出力する
$ awk '{for(i = NF; i > 0; i--){printf("%s ", $i)}printf("\n")}' input.txt
$ perl -nlae '@F=reverse @F; print "@F"' input.txt
awkの方が長くなってしまう。perlにはreverse関数があるので簡潔に書ける。
18. すべての行の各カラムの合計を出力する
$ awk '{sum = 0; for(i = 1; i <= NF; i++){sum += $i}print sum}' input.txt
$ perl -nlae '$sum=0; for(@F){$sum += $_}print $sum' input.txt
19. すべての行のすべてのカラムを合計してその値を出力する
$ awk '{for(i = 1; i <= NF; i++){sum += $i}}END{print sum}' input.txt
$ perl -nlae 'for(@F){$sum += $_}END{print $sum}' input.txt
20. 各カラムの値を絶対値に置き換えてからすべての行を出力する
$ awk '{for(i = 1; i <= NF; i++){if($i<0){$i *= -1}}print }' input.txt
$ perl -nlae '@F = map{abs($_)} @F; {print "@F"}' input.txt
perlには絶対値を返す関数absがあるが、awkにはない。perlではmap関数を使うことにより簡潔にかける。
後半の、for文を使うようなものではperlの方が短くなった。
トラックバック - http://d.hatena.ne.jp/FKD000/20101206/p1
リンク元
- 3 http://twitter.com/
- 3 http://www.wikiwix.com/
- 2 http://ezsch.ezweb.ne.jp/search/?query=ドイツ戦車工場&start-index=16&adpage=4&ct=1301&sr=0000&t=20101207054718&filter=1
- 2 http://www.google.co.jp/search?q=マージソート+fortran&rls=com.microsoft:ja:IE-SearchBox&ie=UTF-8&oe=UTF-8&sourceid=ie7&rlz=1I7ADRA_ja&redir_esc=&ei=xej9TJCrA8birAf24vWDCA
- 1 http://blogsearch.google.co.jp/blogsearch?hl=ja&ie=UTF-8&q=perl&btnG=ブログ検索&lr=lang_ja
- 1 http://d.hatena.ne.jp/dplusplus/20100126/p1
- 1 http://d.hatena.ne.jp/mobile
- 1 http://ggutter.blogspot.com/2009/03/urxvt-rxvt-unicode.html
- 1 http://hootsuite.com/dashboard
- 1 http://mobile.twitter.com/