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 '16 at 7:08
  • yeah but one line is just blank Feb 27 '16 at 7:15
  • 3
    what's wrong with cat -n?
    – cas
    Feb 27 '16 at 7:17
  • forgot to mention the question said dont use "cat -n" Feb 27 '16 at 7:26
  • 1
    Is it homework? Feb 27 '16 at 10:39

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 '16 at 7:27
  • Then use '''( let n=0; while read line; do echo "$n $line"; let n++; done )'''
    – Andrew
    Feb 27 '16 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 '16 at 7:47
  • 1
    And also there is "-b" flag for "cat"...
    – Andrew
    Feb 27 '16 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 '16 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 '16 at 21:43
  • fyi, your awk example can be simplified to awk '!!$0{ print ++a,$0; }'
    – user14755
    Feb 29 '16 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 '16 at 2:15
  • awk NF is the usual idiom for non-blank lines. Dec 9 '20 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


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.