Grep Command – How to Skip N Lines and Search After

grep

I have a huge log file and want to grep the first occurrence of a pattern, and then find another pattern right after this occurence.

For example:

123
XXY
214
ABC
182
558
ABC
856
ABC

In my example, I would like to find 182 and then find the next occurrence of ABC

The first occurrence is simple:

grep -n -m1 "182" /var/log/file

This outputs:

5:182

How do I find the next occurrence of ABC?

My idea was to tell grep to skip the first n lines (in the above example n=5), based on the line number of 182. But how do I do that?

Best Answer

With sed you can use a range and quit input at a single completion:

sed '/^182$/p;//,/^ABC$/!d;/^ABC$/!d;q'

Similarly w/ GNU grep you can split the input between two greps:

{ grep -nxF -m1 182; grep -nxF -m1 ABC; } <<\IN
123
XXY
214
ABC
182
558
ABC
856
ABC
IN

... which prints...

5:182
2:ABC

... to signify that the first grep found a -Fixed-string literal, -xentire-line 182 match 5 lines from the start of its read, and the second found a similarly typed ABC match 2 lines from the start of its read - or 2 lines after the first grep quit reading at line 5.

From man grep:

-m NUM, --max-count=NUM
          Stop  reading  a  file  after  NUM  matching
          lines.   If the input is standard input from
          a regular file, and NUM matching  lines  are
          output, grep ensures that the standard input
          is  positioned  to  just  after   the   last
          matching  line before exiting, regardless of
          the  presence  of  trailing  context  lines.
          This  enables  a calling process to resume a
          search. 

I used a here-document for the sake of reproducible demonstration, but you should probably do:

{ grep ...; grep ...; } </path/to/log.file

It will also work with other shell compound-command constructs like:

for p in 182 ABC; do grep -nxFm1 "$p"; done </path/to/log.file
Related Question