I need to write a program that reads lines from a file on stdin and writes the lines to stdout with line numbers. I cannot use cat -n.

Let's say the text file had this:


 nopqr st

It should basically read those lines and output those lines but with lines numbers.

This is the while read loop I have but it doesn't print out every line.

while read line
    awk '{print NR, $0}'

done < file

Basically what this output is this:

1 ghi
3 klm
4 nopqr   st

For some reason the abcdef doesn't show up and number 2 isn't supposed to be blank.

  • 2
    You don't need the loop, Awk can handle this: awk '{print NR, $0}' file...
    – jasonwryan
    Feb 27, 2016 at 7:08
  • yeah but one line is just blank Feb 27, 2016 at 7:15
  • 3
    what's wrong with cat -n?
    – cas
    Feb 27, 2016 at 7:17
  • forgot to mention the question said dont use "cat -n" Feb 27, 2016 at 7:26
  • 1
    Is it homework? Feb 27, 2016 at 10:39

4 Answers 4


Have you tried nl -b a <file_name>

debian@virt00:~/test$ nl -b a file
     1  abcdef
     2   ghi
     4   klm
     5   nopqr st
  • nl stands for number line
  • -b flag for body numbering
  • 'a' for all lines.

for more information http://linux.die.net/man/1/nl


You may use "cat -n", flag "-n" is to add the numbers to the output lines of "cat".

  • Edited the main question, can't use "cat -n" Feb 27, 2016 at 7:27
  • Then use '''( let n=0; while read line; do echo "$n $line"; let n++; done )'''
    – Andrew
    Feb 27, 2016 at 7:33
  • @shawnedward if the reason not to used cat -n are the empy lines then delete them first sed "/^$/d" | cat -n Feb 27, 2016 at 7:47
  • 1
    And also there is "-b" flag for "cat"...
    – Andrew
    Feb 27, 2016 at 7:52
  • 1
    and last but not least cat -n | sed -e '/^[ \t0-9]*$/d' would include empty lines in numbering yet not print those lines (which would be a cat --number-all-only-show-nonblank of sorts) Feb 27, 2016 at 8:07
awk '$0!=""{print NR, $0}' file

The $0 != "" means $0 not equal to empty. For those lines print line number and line.

That will produce this output:

1 abcdef
2 ghi
4 klm
5 nopqr st

with the old line numbers. If you need the output with the new line numbers:

awk '$0!=""{a++; print a, $0}' file

1 abcdef
2 ghi
3 klm
4 nopqr st

To explain how your script worked:

The line with read line will read the first line (you do not print it).
Then, you connect the file to awk and it process all the other lines.
Awk does not (by default) obviate empty lines, so the empty line is also printed.

There are many ways to solve this, the one above seems as simple as is possible.

  • Upvoted for explanation of what was wrong with OP's attempt.
    – John Auld
    Feb 27, 2016 at 21:43
  • fyi, your awk example can be simplified to awk '!!$0{ print ++a,$0; }'
    – user14755
    Feb 29, 2016 at 2:04
  • @DarkHeart Of course, you are right. Trying to be KISS. :-) ..... Of course, note that this also works: awk '$0{print ++a, $0}' file.
    – user79743
    Feb 29, 2016 at 2:15
  • awk NF is the usual idiom for non-blank lines. Dec 9, 2020 at 17:28

awk '!/^$/{print ++a, $0}' file


awk '!!$0{print ++a, $0}' file


awk '{if ($0 != "") print ++aa, $0}' file


while read -r
    [[ "${REPLY}" = "" ]] || echo $((++NR)) "${REPLY}"
done < file


You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .