Help us understand the problem. What is going on with this article?

コマンドラインツールとしてのperl

More than 1 year has passed since last update.

みなさん!Perlつかってますか!
ぼくは日常的に使ってます。

さて、PerlはCPANモジュールを駆使して適切な設計さえ行えば、大規模なWebアプリも構築できるほどパワフルな言語ではありますが、その本領はやはりコマンドラインツールやスクリプトとしての使われ方でしょう。
今回はコマンドラインツールとしてのperlの使い方を簡単に紹介します。

コマンドラインツール

多くのコマンドラインツールにはGNU系とBSD系の異なる実装が存在します。
たとえば、文字列置換によく使うsedはBSD系とGNU系でちょっとオプションが異なったりしますよね。
perlsedgrepの代替としても使うことができるわけですが、perlでそれら代替する最大の利点はOSが異なっても同じインターフェイスで扱えることでしょう。
一度覚えて手癖にしてしまえば急場でもOSの違いを気にせずにサッとログをまとめたりCSVなどを処理したりできるわけです。便利でしょー。
簡単にsedgrepをどのように代替することができるのかを見ていきます。

sedの代替

sedにpipeされた入力をFooからBarに置換するにはたとえばこのようにすれば良いでしょう。

... | sed -e 's/Foo/Bar/g'

perlで代替するとこうなります。

... | perl -pe 's/Foo/Bar/g'

ほぼ変わらないですね!
perl -pesed -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 -negrep の代わりとして使うことが出来ます。

当然ながら、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/;
}

まとめ

perlsedなどの各種コマンドラインツールを代替できるほか、パワフルなのでちょっと書くだけで様々な処理が行えることを示しました。
これを期に日常の仕事をより豊かにするためにperlをもっと活用してみては如何でしょうか。

最後にperlのワンライナーでよく僕が使うdirty hackを紹介して終わりにします。
Fooを含む行をカウントするワンライナーです。

... | perl -nle '$foo++ if /Foo/}{print $foo'

答え合わせは -MO=Deparse でどうぞ。

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした