perl とか学生時代にはじめて Web に触れたとき以来ほとんど触ったことありませんが、たまにワンライナーで sed の代わりにつかうと便利です。
大抵の環境でインストールされているし、python も大抵の環境でインストールされているけどワンライナーには向かないし。
コマンドラインオプションの説明
-e <program>
実行するスクリプトの内容を指定します。perl をワンライナーで使用するならこれは必須です。
-p
入力データの各行を処理して出力します。入力行は $_
に入ります。
概ね次のようなコードと同じです(イメージ)。
while (<>) {
... script ...
} continue {
print;
}
-n
入力データの各行を処理します。-p
から出力を取り除いたものです。
while (<>) {
... script ...
}
-l[octal]
スクリプトの処理前に行を chomp し、さらに print で出力時に改行を追加します。8進数で文字を指定すると print で出力時に追加される文字を指定できます。
-l
を使わないかぎり $_
とか後述の $F
の最後とかには改行も含まれています。sed や awk と同じ感覚で使うなら -l
も付けておくと良いでしょう。
-0[octal]
8進数で行のセパレータ文字を指定します。省略すればヌル文字になります。
例えば find の -print0 と組み合わせて次のように使います。
find . -name '*.bak' -print0 | perl -0ne unlink
-a
-n
や -p
と一緒に使用すると、スクリプトの実行前に行を分割して @F
に代入します。
awk っぽい使い方ができます。
ip -o addr show | perl -anle 'print $F[3]'
-F<pattern>
-a
で行を分割するときのセパレータを指定します。
cat /etc/passwd | perl -aF: -lne 'print $F[2]'
指定されたものは正規表現と解釈されます。
echo -e 'aaa123bbb\nccc456ddd' | perl -aF'\d+' -lne 'print $F[1]'
修飾子を付けて指定することもできます。
echo -e '12a34\n56Z78' | perl -aF'/[a-z]/i' -lne 'print $F[1]'
-i[extension]
入力ファイルを処理結果で上書きします。extension
を指定すると元ファイルに拡張子を付与してバックアップします。
sed の -i
と同じです。
perl の補足
perl はいろんなところで変数が省略できるようになっており、下記のコードだと、
while (<>) {
... script ...
} continue {
print;
}
下記のコードと同じです(たぶん)。
while ($_ = <>) {
... script ...
} continue {
print $_;
}
他の制御文とかでも、変数を省略すると自動的に $_
が使われます。
例えば、下記のコードは、
print if /foo/
下記のコードと同じです(たぶん)。
print $_ if $_ =~ /foo/
普通にコードを書く分には気持ち悪いことこのうえないですが、ワンライナーするには便利です。
使用例
てきとうな入力データを作ります。
cat <<EOS> hoge.log
foo123bar,ore,,123
foofoo456,are,,456
barbar789,sore,,789
EOS
foo を ___ に置換します。もちろんこの程度なら sed でも余裕です。
# sed の場合
cat hoge.log | sed 's/foo/___/g'
# perl の場合
cat hoge.log | perl -pe 's/foo/___/g'
正規表現に一致する最初の行を表示します。これも sed でも余裕です。
# sed の場合
cat hoge.log | sed -rn '/are/{p;q}'
# perl の場合
cat hoge.log | perl -lne 'print,exit if /are/'
正規表現に一致する部分文字列を返します。grep で一応できます。
# grep の場合
cat hoge.log | grep -Po 'foo\d+'
# perl の場合
cat hoge.log | perl -lne 'print $1 if /(foo\d+)/'
正規表現のサブパターンだけを返します。たぶん sed や grep だと辛いです。
# perl の場合
cat hoge.log | perl -lne 'print $1 if /foo(\d+)/'
区切り文字で分割した2番目の項目を出力します。これは awk でも余裕です。
# awk の場合
cat hoge.log | awk -F, '{print $2}'
# perl の場合
cat hoge.log | perl -aln -F, -e 'print $F[1]'
正規表現で分割した2番目の項目を出力します。たぶん awk だと辛いです。
# perl の場合
cat hoge.log | perl -aln -F'/,+/' -e 'print $F[2]'
ruby のワンライナーのためのコマンドラインオプション
実は ruby にもほとんど同じようなコマンドラインオプションがあります。