< Previous | Contents | Next >
nl – Number Lines
The nl program is a rather arcane tool used to perform a simple task. It numbers lines. In its simplest use, it resembles cat -n:
[me@linuxbox ~]$ nl distros.txt | head
1 | SUSE | 10.2 | 12/07/2006 |
2 | Fedora | 10 | 11/25/2008 |
3 | SUSE | 11.0 | 06/19/2008 |
4 | Ubuntu | 8.04 | 04/24/2008 |
5 | Fedora | 8 | 11/08/2007 |
6 | SUSE | 10.3 | 10/04/2007 |
7 | Ubuntu | 6.10 | 10/26/2006 |
8 | Fedora | 7 | 05/31/2007 |
9 | Ubuntu | 7.10 | 10/18/2007 |
10 | Ubuntu | 7.04 | 04/19/2007 |
Like cat, nl can accept either multiple files as command line arguments, or standard in- put. However, nl has a number of options and supports a primitive form of markup to al- low more complex kinds of numbering.
nl supports a concept called “logical pages” when numbering. This allows nl to reset (start over) the numerical sequence when numbering. Using options, it is possible to set the starting number to a specific value and, to a limited extent, its format. A logical page is further broken down into a header, body, and footer. Within each of these sections, line numbering may be reset and/or be assigned a different style. If nl is given multiple files, it treats them as a single stream of text. Sections in the text stream are indicated by the presence of some rather odd-looking markup added to the text:
Table 21-1: nl Markup
Markup Meaning
Markup Meaning
\:\:\: Start of logical page header
\:\: Start of logical page body
\: Start of logical page footer
Each of the above markup elements must appear alone on its own line. After processing a markup element, nl deletes it from the text stream.
Here are the common options for nl:
Table 21-2: Common nl Options
Option Meaning
Option Meaning
-b style Set body numbering to style, where style is one of the following:
a = number all lines
t = number only non-blank lines. This is the default.
n = none
pregexp = number only lines matching basic regular expression
regexp.
-f style Set footer numbering to style. Default is n (none).
-h style Set header numbering to style. Default is n (none).
-i number Set page numbering increment to number. Default is one.
-n format Sets numbering format to format, where format is:
ln = left justified, without leading zeros.
rn = right justified, without leading zeros. This is the default.
rz = right justified, with leading zeros.
-p Do not reset page numbering at the beginning of each logical page.
-s string Add string to the end of each line number to create a separator.
Default is a single tab character.
-v number Set first line number of each logical page to number. Default is one.
-w width Set width of the line number field to width. Default is 6.
Admittedly, we probably won’t be numbering lines that often, but we can use nl to look at how we can combine multiple tools to perform more complex tasks. We will build on our work in the previous chapter to produce a Linux distributions report. Since we will be using nl, it will be useful to include its header/body/footer markup. To do this, we will add it to the sed script from the last chapter. Using our text editor, we will change the script as follows and save it as distros-nl.sed:
# sed script to produce Linux distributions report
1 i\
\\:\\:\\:\
\
Linux Distributions Report\
\
Name Ver. Released\
---- ---- --------\
\\:\\:
s/\([0-9]\{2\}\)\/\([0-9]\{2\}\)\/\([0-9]\{4\}\)$/\3-\1-\2/
$ a\
\\:\
\
End Of Report
# sed script to produce Linux distributions report
1 i\
\\:\\:\\:\
\
Linux Distributions Report\
\
Name Ver. Released\
---- ---- --------\
\\:\\:
s/\([0-9]\{2\}\)\/\([0-9]\{2\}\)\/\([0-9]\{4\}\)$/\3-\1-\2/
$ a\
\\:\
\
End Of Report
The script now inserts the nl logical page markup and adds a footer at the end of the re- port. Note that we had to double up the backslashes in our markup, because they are nor - mally interpreted as an escape character by sed.
Next, we’ll produce our enhanced report by combining sort, sed, and nl:
[me@linuxbox ~]$ sort -k 1,1 -k 2n distros.txt | sed -f distros-nl.s ed | nl
Linux Distributions Report
Name | Ver. | Released |
---- | ---- | -------- |
1 | Fedora | 5 | 2006-03-20 |
2 | Fedora | 6 | 2006-10-24 |
3 | Fedora | 7 | 2007-05-31 |
4 | Fedora | 8 | 2007-11-08 |
5 | Fedora | 9 | 2008-05-13 |
6 | Fedora | 10 | 2008-11-25 |
7 | SUSE | 10.1 | 2006-05-11 |
8 | SUSE | 10.2 | 2006-12-07 |
9 | SUSE | 10.3 | 2007-10-04 |
10 | SUSE | 11.0 | 2008-06-19 |
11 | Ubuntu | 6.06 | 2006-06-01 |
12 | Ubuntu | 6.10 | 2006-10-26 |
13 | Ubuntu | 7.04 | 2007-04-19 |
14 | Ubuntu | 7.10 | 2007-10-18 |
15 | Ubuntu | 8.04 | 2008-04-24 |
16 | Ubuntu | 8.10 | 2008-10-30 |
End Of Report
Our report is the result of our pipeline of commands. First, we sort the list by distribution name and version (fields 1 and 2), then we process the results with sed, adding the re- port header (including the logical page markup for nl) and footer. Finally, we process the result with nl, which, by default, only numbers the lines of the text stream that belong to the body section of the logical page.
We can repeat the command and experiment with different options for nl. Some interest- ing ones are:
nl -n rz
nl -n rz
and
nl -w 3 -s ' '
nl -w 3 -s ' '