sed: cat -n

1 
1 7.10 Numbering Lines
1 ====================
1 
1 This script replaces 'cat -n'; in fact it formats its output exactly
1 like GNU 'cat' does.
1 
1    Of course this is completely useless and for two reasons: first,
1 because somebody else did it in C, second, because the following
1 Bourne-shell script could be used for the same purpose and would be much
1 faster:
1 
1      #! /bin/sh
1      sed -e "=" $@ | sed -e '
1        s/^/      /
1        N
1        s/^ *\(......\)\n/\1  /
1      '
1 
1    It uses 'sed' to print the line number, then groups lines two by two
1 using 'N'.  Of course, this script does not teach as much as the one
1 presented below.
1 
1    The algorithm used for incrementing uses both buffers, so the line is
1 printed as soon as possible and then discarded.  The number is split so
1 that changing digits go in a buffer and unchanged ones go in the other;
1 the changed digits are modified in a single step (using a 'y' command).
1 The line number for the next line is then composed and stored in the
1 hold space, to be used in the next iteration.
1 
1      #!/usr/bin/sed -nf
1 
1      # Prime the pump on the first line
1      x
1      /^$/ s/^.*$/1/
1 
1      # Add the correct line number before the pattern
1      G
1      h
1 
1      # Format it and print it
1      s/^/      /
1      s/^ *\(......\)\n/\1  /p
1 
1      # Get the line number from hold space; add a zero
1      # if we're going to add a digit on the next line
1      g
1      s/\n.*$//
1      /^9*$/ s/^/0/
1 
1      # separate changing/unchanged digits with an x
1      s/.9*$/x&/
1 
1      # keep changing digits in hold space
1      h
1      s/^.*x//
1      y/0123456789/1234567890/
1      x
1 
1      # keep unchanged digits in pattern space
1      s/x.*$//
1 
1      # compose the new number, remove the newline implicitly added by G
1      G
1      s/\n//
1      h
1