みなさん!Perlつかってますか!
ぼくは日常的に使ってます。
さて、PerlはCPANモジュールを駆使して適切な設計さえ行えば、大規模なWebアプリも構築できるほどパワフルな言語ではありますが、その本領はやはりコマンドラインツールやスクリプトとしての使われ方でしょう。
今回はコマンドラインツールとしてのperlの使い方を簡単に紹介します。
コマンドラインツール
多くのコマンドラインツールにはGNU系とBSD系の異なる実装が存在します。
たとえば、文字列置換によく使うsedはBSD系とGNU系でちょっとオプションが異なったりしますよね。
perlはsedやgrepの代替としても使うことができるわけですが、perlでそれら代替する最大の利点はOSが異なっても同じインターフェイスで扱えることでしょう。
一度覚えて手癖にしてしまえば急場でもOSの違いを気にせずにサッとログをまとめたりCSVなどを処理したりできるわけです。便利でしょー。
簡単にsedやgrepをどのように代替することができるのかを見ていきます。
sedの代替
sedにpipeされた入力をFooからBarに置換するにはたとえばこのようにすれば良いでしょう。
... | sed -e 's/Foo/Bar/g'
perlで代替するとこうなります。
... | perl -pe 's/Foo/Bar/g'
ほぼ変わらないですね!
perl -pe で sed -e の代わりとして使うことが出来ます。
もちろん、ファイルを置換してバックアップをつくる -i オプションも同様に使うことが出来ます。簡単ですね!
原理
これがどのように動いているのかを簡単に解説します。
-e オプションは続く引数をコードとして解釈するものです。
-p オプションはコードを以下のように展開して実行するモードになります。(-MO=Deparseを付けて実行するとどのようなコードが実行されるのかよくわかります。)
LINE: while (defined($_ = readline ARGV)) {
s/Foo/Bar/g;
}
continue {
die "-p destination: $!\n" unless print $_;
}
ARGV という特殊なファイルハンドルを読むことで、引数または標準入力を$_に読んでからコードを実行することになります。
このとき、 s/Foo/Bar/g はそのマッチ対象が指定されていないため $_ を対象に動作し、continueブロックのprint $_で出力されるというカラクリになっています。
詳しくはARGVなどについてのドキュメントを参照するとよいでしょう:
grepの代替
grepにpipeされた入力からFooを含むものだけに絞るにはたとえばこのようにすれば良いでしょう。
... | grep 'Foo'
perlで代替するとこうなります。
... | perl -ne 'print if /Foo/'
ちょっとコードっぽくなりましたが、分かりやすいかとおもいます。
perl -ne で grep の代わりとして使うことが出来ます。
当然ながら、Perlなのでもう少し凝ったマッチをさせることもできます。
たとえば、名前解決をした上で 192.168. で開始するものを抽出したいとなればこのようにすることでそれができます。
... | perl -MSocket -nle 'print if Socket::inet_ntoa(scalar gethostbyname($_)) =~ /^192\.168\.*/'
また、応用として Fooを含む行をカウントしたければこのようにするとよいです。
... | perl -nle '$foo++ if /Foo/; END{ print $foo }'
ね、簡単でしょ?
原理
-e オプションは先程と同じです。
-n オプションは-pオプションと似た動きをしますがprintをしません。
よって perl -ne 'print if /Foo/' は以下のように展開されます。
LINE: while (defined($_ = readline ARGV)) {
print $_ if /Foo/;
}
まとめ
perlはsedなどの各種コマンドラインツールを代替できるほか、パワフルなのでちょっと書くだけで様々な処理が行えることを示しました。
これを期に日常の仕事をより豊かにするためにperlをもっと活用してみては如何でしょうか。
最後にperlのワンライナーでよく僕が使うdirty hackを紹介して終わりにします。
Fooを含む行をカウントするワンライナーです。
... | perl -nle '$foo++ if /Foo/}{print $foo'
答え合わせは -MO=Deparse でどうぞ。