2

I have a text file with a format similar to:

PktType1 Header
PktType1 Pay
PktType1 Done
PktType0 Header
PktType0 Pay
PktType0 Done
...

What I'm trying to do is grep for all occurrences of PktType0 Done and then annotate which Nth occurrence it is along with the line number. For example:

1 42 PktType0 Done
2 65 PktType0 Done
3 75 PktType0 Done

Where 42, 65 and 75 are the line numbers and 1, 2 and 3 are simply a count of the occurrences. I suppose I could write it to a file and then show the line numbers. But I was wondering if there's a tool I can pipe this to that will do the same.

1
  • 1
    Always show expected output that you can get from the sample input you provide, not different output you could get from some other input. We need sample input/output we can copy/paste to test with to get a pass/fail result.
    – Ed Morton
    Dec 1 '21 at 12:42
5

If you are looking to do beyond just pattern matching, and do additional formatting with line numbers and the match count, Awk is a better choice then grep

awk '/PktType0 Done/{ print ++count, NR, $0 }' file
1

I was wondering if there's a tool I can pipe this to that will do the same.

Yes: nl

<log.txt grep -n 'PktType0 Done' | nl
1

With example data taken from another answer:

$ cat file
PktType0 Done
PktType1 Header
PktType1 Pay
PktType0 Done
PktType1 Done
PktType0 Header
PktType0 Pay
PktType0 Done
$ awk '$0 == "PktType0 Done" { print ++count, NR, $0 }' file
1 1 PktType0 Done
2 4 PktType0 Done
3 8 PktType0 Done

The awk command ignores all lines except those precisely equal to the string PktType0 Done. It prints the value of a counter, the current line number, and the line itself.

Change $0 == "PktType0 Done" to /PktType0 Done/ to look for the string as a substring anywhere on any line.

0

Not comparable with an awk solution, but here's an alternative. Given a slightly different sample:

PktType0 Done
PktType1 Header
PktType1 Pay
PktType0 Done
PktType1 Done
PktType0 Header
PktType0 Pay
PktType0 Done

The commands:

$ paste <(awk '/Type0 Done/ { print ++c }' file) <(grep -n 'Type0 Done' file) | tr ':' ' ' | column -t
1  1  PktType0  Done
2  4  PktType0  Done
3  8  PktType0  Done
0
grep -n conf file |
  sed -Ee 's/^([[:digit:]]*):/\1 /' |
  cat -n

The sed step is because grep -n places a colon between the line number and the text, which was not indicated in your desired output.

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.