Perl のオプション (ワンライナー用)
Perl の起動オプションのうち、ワンライナーでよく使うものについて使い方と特徴を説明します。
ワンライナーの指示: -e
ワンライナーとして実行することを指示します。ここではワンライナーの説明をしているので、サンプルにはかならず -e
がついています。
ループの指示: p-
と -n
-p
と -n
はどちらも入力をループして処理するために使います。このとき Perl は while
文で入力を $_
に代入しながらループします1。
-p
と -e
の違いは、-p
はループの処理をしたあと $_
の内容を出力しますが、-n
はしません。print と not-print とすると覚えやすいかもしれません。
while (<>) {
## ワンライナーで書いた処理 ##
print $_;
}
while (<>) {
## ワンライナーで書いた処理 ##
}
それぞれ -n
と -p
を指定したワンライナーを、それぞれ展開してみます。
$ perl -ne 'printf("%4d: %s", ++$i, $_)'
$ perl -pe 'printf("%4d: ", ++$i)'
↓
# -ne オプション
while (<>) {
printf("%4d: %s", ++$i, $_);
}
# -pe オプション
while (<>) {
printf("%4d: ", ++$i)
printf $_;
}
改行の特殊取り扱い: -l
ループするときに、$_
に行をセットするときに末尾の改行を取り除きます。かつ、-p
がある場合、行を出力するときに改行を末尾に付けます。
※Windows は改行コードが CR+LF
なので、Perl インタプリタによっては(たとえば ActivePerl なのか、Git for Windows のものか、など)正しく動作しない可能性があります。
while (<>) {
chomp();
## ワンライナーで書いた処理 ##
if ( print ) {
print;
print "\n";
}
}
自動splitモード: -a
ループのとき、各行を処理する前に split
関数で分割し、リスト @F
に格納します。
# perl -ane 'print $F[0]' inu.txt
while (<>) {
@F = split(' ');
print $F[0]; # @F の最初の要素を表示します
}
分割する文字(正確には split
関数の引数なので、正規表現ももちろん使えます)は、標準ではスペースですが -F
で変更できます。たとえば下のコードだと ,
(カンマ) になります。
# perl -F, -ane 'print $F[-1]' sample.csv
while (<>) {
@F = split(',');
print $F[-1]; # @F の最後の要素を表示します
}
使う正規表現によっては -F' *'
といったように -F
のオプションを '
か "
でくくる必要があったりするので、くくる必要がないときでもくくるようにすると小さなミスを減らせると思います。
書き換え(書き戻し)モード: -i
-i
は、一般的にはオプションをつけて実行します。たとえば -i.bak
とすると、書き換える前のファイルを、ファイル名の最後に .bak
を付け加えてコピーを取ってから書き換えます。
たとえば
$ perl -pe -i.bak `s/apple/ringo/` neko.txt tora.txt inu.txt
とすると、perl は neko.txt
を neko.txt.bak
にコピーし、それから apple を ringo に置換して、neko.txt
に書き込みます。tora.txt
と inu.txt
も同様です。
-i
だけ指定した場合はコピーせず、開いたファイルに変更後の内容を書き戻します。特別な理由がなければ、ちゃんとオプションを付けた方がいいと思います。
オプション以外に覚えておくと便利なこと
BEGIN ブロックと END ブロック
オプションではないですが、BEGIN
と END
を使うことはとても多いです。ループモードのときに、前処理と後処理を書くために使います。
いちばんよく使うのは、ループ内でなにか計算をして END
で結果を出力するパターンです。
$ perl -ne '++$lines; END {print $lines}'
このワンライナーは入力の行数を表示します。(wc -l
相当です)
入力のしかた
ワンライナーの入力は、
- パイプ(標準入力)で渡す
- 引数で指定したファイルで渡す
の2通りです。
ただし両方は使えません。引数があると標準入力は無視され、引数で渡したファイルの中身だけになります。
引数では、複数のファイルを指定できます。
$ cat neko.txt
111
$ cat tora.txt
222
$ cat inu.txt
333
$ cat neko.txt | perl -pe '' tora.txt inu.txt
222
333
$ cat neko.txt | perl -pe ''
111
いくつかのオプション(-i
など)を使うときは引数でファイルを渡す必要があります。
-
$_
は「暗黙の変数」と呼ばれ、変数を指定しなかった場合に使われるデフォルトの変数です。コードの可読性が悪くなる(ことが多い)ので他言語の利用者からはいい顔をされないのですが、Perl のワンライナーでは$_
を使うことを前提とすることがほとんどです。 ↩