5

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:

 abcdef
 ghi

 klm
 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
do
    awk '{print NR, $0}'

done < file

Basically what this output is this:

1 ghi
2 
3 klm
4 nopqr   st

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

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

4 Answers 4

8

Have you tried nl -b a <file_name>

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

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

3

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

5
  • Edited the main question, can't use "cat -n" Commented Feb 27, 2016 at 7:27
  • Then use '''( let n=0; while read line; do echo "$n $line"; let n++; done )'''
    – Andrew
    Commented 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 Commented Feb 27, 2016 at 7:47
  • 1
    And also there is "-b" flag for "cat"...
    – Andrew
    Commented 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) Commented Feb 27, 2016 at 8:07
3
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.

4
  • Upvoted for explanation of what was wrong with OP's attempt.
    – John Auld
    Commented Feb 27, 2016 at 21:43
  • fyi, your awk example can be simplified to awk '!!$0{ print ++a,$0; }'
    – user14755
    Commented 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
    Commented Feb 29, 2016 at 2:15
  • awk NF is the usual idiom for non-blank lines. Commented Dec 9, 2020 at 17:28
-1
#!/bin/bash

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

echo

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

echo

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

echo

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

echo

You must log in to answer this question.

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