Posted at

ワンライナーのための perl コマンドラインオプション入門

More than 3 years have passed since last update.

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 にもほとんど同じようなコマンドラインオプションがあります。