1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

nlコマンドAdvent Calendar 2020

Day 5

行番号の桁数を変更するnlコマンドのwオプション

Last updated at Posted at 2020-12-04

nlコマンドはwオプションを指定することで、行番号の桁数を変更することができます。

wオプションの使い方

まずはマニュアルを参照してみましょう。

info nl (GNU coreutils)

‘-w NUMBER’
‘--number-width=NUMBER’
     Use NUMBER characters for line numbers (default 6).

coreutilsは非常にシンプルに記載されています。桁数を変更するには-wのあとに数字を指定するだけです。そして-nオプションの記事で調べたとおり、デフォルトの桁数は6桁になります。

busybox nl --help

	-w N		Width of line numbers

busyboxでも-wオプションは使うことができます。ヘルプはcoreutils以上にシンプルな記述です。

man nl (BSD)

     -w width     Specify the number of characters to be occupied by the line num-
                  ber; in case the width is insufficient to hold the line number,
                  it will be truncated to its width least significant digits.  The
                  default width is 6.

一方でBSDのマニュアルにはcoreutilsに比べて長い説明が書かれています。主な差分は「幅が行番号を保持するのに十分でない場合、行番号は有効な幅の桁数以下に切り捨てられる」ということのようです。これはあとで検証してみましょう。

POSIX

-w width
Specify the number of characters to be used for the line number. The default width shall be 6.

出典:https://pubs.opengroup.org/onlinepubs/9699919799/utilities/nl.html

ちなみにPOSIXでは「幅が十分でない場合」について言及は無いようです。この条件において互換性は保証されていません。

wオプションを試す

それでは最初の記事で使用したテキストファイル「utl-kita」で実際に試してみましょう。

$ nl -w 1 utl-kita
1	東京
2	上野
3	尾久
4	赤羽
5	浦和
6	さいたま新都心
7	大宮
$ nl -w 10 utl-kita
         1	東京
         2	上野
         3	尾久
         4	赤羽
         5	浦和
         6	さいたま新都心
         7	大宮

たしかに幅が変更されてはいますが、少々わかりにくいです。これを-nでゼロ埋めして出力すればより明瞭になります。

$ nl -n rz -w 2 utl-kita
01	東京
02	上野
03	尾久
04	赤羽
05	浦和
06	さいたま新都心
07	大宮

駅ナンバリング表示の駅番号を出力する

2桁の数字と駅名を表示したら、あの見慣れた表示も出力したくなりますよね。宇都宮線・高崎線の略線記号「JU」を付加すれば、駅ナンバリング表示の駅番号を出力することができます。プリフィックスの付加には、sed(Stream EDitor)というテキストを編集するコマンドを組み合わせます。

$ nl -n rz -w 2 utl-kita | sed 's/^/JU/'
JU01	東京
JU02	上野
JU03	尾久
JU04	赤羽
JU05	浦和
JU06	さいたま新都心
JU07	大宮

sedにも軽く触れておくと、s/^/JU/の部分は、テキストを置換するsコマンドで、正規表現^(行頭)にマッチする部分をJUに置き換えるという意味です。/はただの区切り文字なので、sedの文法上はs@^@JU@などとしても同じ意味になります。

幅が十分でない場合

さきほどBSDのマニュアルで差分があった部分です。しっかり検証しておきましょう。6桁から7桁になるとき、つまり999999から1000000になる部分を出力して試してみます。

まずはcoreutilsから。

coreutils
$ yes | head -n 1000000 | nl | tail -n 2
999999	y
1000000	y

7桁の数字もきちんと出力されています。もちろん-wでデフォルト以外の桁数を指定しても同様の挙動になります。

coreutils
$ yes | head -n 100 | nl -w 2 | tail -n 2
99	y
100	y

busyboxでも試してみましょう。

busybox
$ yes | head -n 100 | busybox nl -w 2 | tail -n 2
99	y
100	y

他のコマンドにも触れておくと、yesの出力「y」をheadで1000000行あるいは100行を切り取り、nlで行番号を付加してからtailで最後の2行だけを出力しています。

続いてBSD系のnlではどうでしょうか。macOSのnlで試してみます。

BSD
$ yes | head -n 1000000 | nl | tail -n 2
999999	y
000000	y

どうやら本当に6桁を超えると上位の桁が切り捨てられるようです。つまり**BSD系のnlでは-wの設定なしに100万行を超える行番号を正しくカウントすることはできません。**念の為に内部的に行番号が正しく保持されているかどうか確認してみましょう。同じ条件で幅を7桁にしてみます。

BSD
$ yes | head -n 1000000 | nl -w 7 | tail -n 2
 999999	y
1000000	y

この場合はきちんと7桁の数字が出力されました。行番号自体は正しく保持されているようです。

以上の検証結果をまとめると、coreutilsとbusyboxのnlでは-wは最小の桁数を指定しており、桁が大きくなった場合その幅は可変です。一方で、BSD系のnlでは-wは固定の桁数を指定しており、その幅を越えた場合は上位の桁が切り捨てられます。このようにnlは実装によって桁の取り扱いが異なり、-wの設定値を意識しなければならない場面もありそうです。


1
0
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
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?