週末には少しPerlを。

Perlスクリプトの学習日記です。

エスキモーの挨拶を知り、初めてPerlの秘密の演算子に触れる

ワンライナーでよく登場する奇妙なコードの書き方は「secret operator」と呼ばれニックネームがつけられて いるようです。

参考: CPANのperlsecret

実際には演算子でもなんでもない、そんな奇妙な書き方に困惑しつつ Famous Perl One-Liners の読書メモの2回めです。

行番号をつけてファイル出力

perl -pe '$_ = "$. $_"'

変数 $. は $INPUT_LINE_NUMBER, すなわち行番号。 表示に書式指定もできます。

perl -ne 'printf "%-5d %s", $., $_'

空行以外を数え上げる

perl -pe '$_ = ++$a." $_" if /./'

変数 $a は use strict していないので自動的に作成され ゼロで初期化されます。 「/./」は空行以外にマッチする正規表現。「.」は改行以外の任意の文字にマッチするので。

正規表現にマッチした行のみを数え表示する

perl -ne 'print ++$a." $_" if /regex/'

行数を表示する

perl -lne 'END { print $.}'

wc -l と打てばいいところを敢えてPerlで。 スイッチ -l はoutput record separatorを改行文字にします。

別解としてファイルを一度リストコンテキストで読み込んでから スカラーコンテキストで評価して表示する方法:

perl -le 'print $n=()=<>'

「=()=」の部分は goatse operator と呼ばれるそうで、 その名前の由来を画像検索してはならないとのこと。 perlsecretの記述をそのまま引用すると、

If you don't understand the name of this operator, consider yourself lucky. 
You are advised not to search the Internet for a visual explanation.

さらに別解。

perl -lne '}{ print $.'

「}{」は eskimo operator と呼ばれるそうです。 恥ずかしながら本当にそういう演算子があるのかと思ったことを ここに告白いたします。

実際にはこれは単に次と等価。

while (<>) {
}{
    print $.
}

その名前の由来について perlsecret から引用:

Ethnographic note: 
in modern Western culture, 
an eskimo kiss is the act of pressing the tip of one's nose 
against another's. 
It is loosely based on a traditional Inuit greeting called a kunik, 
that early explorers of the Arctic dubbed "Eskimo kissing" 
when they first witnessed it. 
The kunik itself is not a kiss, not erotic, 
and simply of form of affectionate greeting.

空行以外の行数を表示する

perl -le 'print scalar(grep {/./}<>)'

もう少し短くすると

perl -le 'print ~~ grep /./,<>'

ビット反転の「~」を2つ重ねた「~~」は 「Inchworm」と呼ばれる。

正規表現にマッチした行数を表示

perl -lne '$a++ if /regex/; END{print $a+0}'

数値として評価するための「+0」は金星に似ている姿から「Venus operator」と呼ばれるとのこと。