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などでおもしろい方法を見つけたら追記していこうと思います。