LoginSignup
0
1

More than 3 years have passed since last update.

スクリプトでnlコマンドを代替する

Posted at

nlコマンドを用いずにテキストに行番号をつける方法をまとめます。あまり細かい挙動にはこだわりません。今回はスクリプト編です。

AWK

ワンライナースクリプトの定番といえばAWKですね。

NR

$ yes | head | awk '$0=NR"\t"$0'
1   y
2   y
3   y
4   y
5   y
6   y
7   y
8   y
9   y
10  y

NR(Number of Records)はレコードの番号が格納されたビルトイン変数です。デフォルトのレコードセパレータが改行なので、そのまま行番号に対応します。
上記はアクションレス記法ですが、ちゃんと書くなら以下のようになります。デフォルトのフィールドセパレータはスペースなので、ビルトイン変数のOFSをタブで上書きしています。

$ yes | head | awk -v OFS='\t' '{print NR, $0}'
1   y
2   y
3   y
4   y
5   y
6   y
7   y
8   y
9   y
10  y

この例では書式はlnです。さらにprintf関数を使えば書式の自由度は格段に上がります。たとえば`rz`書式にするなら以下のようにします。

$ yes | head | awk '{printf("%06d\t%s\n", NR, $0)}'
000001  y
000002  y
000003  y
000004  y
000005  y
000006  y
000007  y
000008  y
000009  y
000010  y

Perl

Perlもワンライナーでは定番ですね。

$.

$ yes | head | perl -pe 's/^/$.\t/'
1   y
2   y
3   y
4   y
5   y
6   y
7   y
8   y
9   y
10  y

$.=$NRです。そして書式はlnです。
さらにprintf関数でrz書式を指定するならこんな感じでしょうか。

$ yes | head | perl -pe 'printf "%06d\t",$.'
000001  y
000002  y
000003  y
000004  y
000005  y
000006  y
000007  y
000008  y
000009  y
000010  y
$ yes | head | perl -le 'printf "%06d\t$_",$.while<>'
000001  y
000002  y
000003  y
000004  y
000005  y
000006  y
000007  y
000008  y
000009  y
000010  y

Perlは雰囲気で動いてしまうので、使っていながらなぜこれで動くのかよくわかりません。可読性は微妙ですが、Perlは(バージョンの差はありますが)AWKと違って実装が複数あるわけではないので、移植性の面では優れているのかもしれません。

There’s not a GNU Perl and a BSD Perl – there’s the Perl.
― GNUのPerlもBSDのPerlもなく、ただ『Perl』があるだけだ。

Perlワンライナーの詳細はこちらが参考になると思います。

勉強会の「午前の部」でPerlについて解説されています。


この他にもシェル芸botなどでおもしろい方法を見つけたら追記していこうと思います。

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1