2

grep -n ... prefixes each line with its line number. But the formatting can make the output hard for human interpretation:

$ grep -n hello hello.txt
1:hello my dear
5:hello in another line
17:this is a hello in a two-digits line number
20:another hello in the two-digits line realm
3838813:it's a long file and here comes one last hello

Is there a way to have grep show line numbers in a padded way, for instance with leading zeros or leading spaces?

Example:

$ grep -n -$MAGIC hello hello.txt
      1:hello my dear
      5:hello in another line
     17:this is a hello in a two-digits line number
     20:another hello in the two-digits line realm
3838813:it's a long file and here comes one last hello
RavinderSingh13
  • 130,504
  • 14
  • 57
  • 93
Abdull
  • 26,371
  • 26
  • 130
  • 172
  • No. You'll have to pipe the `grep` output to `sed` or `awk` or any other command that can parse the number of characters before the first `:`. – Jeff Holt Apr 25 '21 at 12:30

5 Answers5

3

No, there's no way to do what you want with just grep but rather than piping grep output to some other tool like awk for the formatting why not only use awk, e.g.:

awk '/hello/{printf "%10d:%s\n", FNR, $0}' hello.txt

e.g. blank-padded:

$ seq 30 | awk '/5/{printf "%10d:%s\n", FNR, $0}'
         5:5
        15:15
        25:25

or zero-padded:

$ seq 30 | awk '/5/{printf "%010d:%s\n", FNR, $0}'
0000000005:5
0000000015:15
0000000025:25

If 10 isn't enough space for the possible line numbers then pick a bigger number or if you want to calculate the field width then you can buffer the matches like @RavinderSing13 shows in their answer. Of course then there's memory and speed of execution hits but that really shouldn't be a problem unless you have literally billions of matches to your regexp in the input.

Ed Morton
  • 188,023
  • 17
  • 78
  • 185
1

With single awk you could try following. Written and tested in GNU awk, should work in any awk.

awk '
/hello/{
  fnr[++count]=FNR
  val[count]=$0
  max=FNR
}
END{
  fmt="%"length(max)"d:%s\n";
  for(i=1;i<=count;i++){
    printf fmt,fnr[i],val[i]
  }
}
'  Input_file

I have tested it with a 350 lines file with hello string in between it has given me output like:

  1:hello
 20:hello
267:hello

Explanation: Adding detailed explanation for above.

awk '                       ##Starting awk program from here.
/hello/{                    ##Checking condition if line has hello in it then do following.
  fnr[++count]=FNR          ##Creating line array with count variable it has current line number.
  val[count]=$0             ##Creating val array with index of count which has current line value.
  max=FNR                   ##max is having current line number.
}
END{                        ##Starting END block of this program from here.
  fmt="%"length(max)"d:%s\n";
  for(i=1;i<=count;i++){    ##Starting a for loop till count here.
    printf fmt,fnr[i],val[i]  ##Printing line(with fnr array) and val array value, with adding spaces before line number as per OP.
  }
}
' Input_file                ##mentioning Input_file name here.
RavinderSingh13
  • 130,504
  • 14
  • 57
  • 93
  • 1
    Sir Ji, your answers are quite impressive and I am kind of obsessed the way you explain it always .. – Piyush Apr 25 '21 at 16:50
  • @Piyush, Thank you for nice words Piyush jee, I try my best to learn and share, cheers. Cheers buddy and happy learning. – RavinderSingh13 Apr 25 '21 at 16:58
1

another solution

$ grep ... | column -ts: | sed -E 's/([0-9]+)( +) /\2\1:/'

       1:hello my dear
       5:hello in another line
      17:this is a hello in a two-digits line number
      20:another hello in the two-digits line realm
 3838813:it's a long file and here comes one last hello

column to align on delimiter : and sed to transform left aligned column to right align.

karakfa
  • 66,216
  • 7
  • 41
  • 56
0

I have created a file, containing some "Errorcodes" and some "Narrowcodes" (the latter just for confirming grep is working fine).

The result of the grep without the formatting is (command grep -i -n "Error" test.txt):

1:Errorcode:null
2:Errorcode:405
3:Errorcode:504
100:Errorcode_100

I have created following command:

grep -i -n "Error" test.txt | awk -F: '{printf ("%05d\n",$1)}'

(This is based on this other StackOverflow post)
Result:

00001
00002
00003
00100

As you see, the leading zeroes part is working fine, but I don't know how to show the rest of the line, but it's already a start.

Dominique
  • 16,450
  • 15
  • 56
  • 112
0

If the purpose of padding the numbers is to sort numerically then you can use the option -n from sort command.

cat file | sort -n