I want to find adjacent matching lines, e.g., if the pattern matches are
$ grep -n pattern file1 file2 file3
file1:10: ...
file2:100: ...
file2:1000: ...
file2:1001: ...
file3:1: ...
file3:123: ...
I want to find the middle two matches:
file2:1000: ...
file2:1001: ...
but not the first two and the last two.
Best Answer
I'll use the same test file as thrig:
Here is an awk solution:
How it works
awk
implicitly loops over every line in the file. This program uses one variable,last
, which contains the last line if it matched regexpat
. Otherwise, it contains the empty string./pat/ && last {print last; print}
If
pat
matches this line and the previous line,last
, was also a match, then print both lines.{last=""}
Replace
last
with an empty string/pat/ {last=$0}
If this line matches
pat
, then setlast
to this line. This way it will be available when we process the next line.Alternative for treating >2 consecutive matches as one group
Let's consider this extended test file:
Unlike the solution above, this code treats the three consecutive matching lines as one group to be printed:
This code uses two variables. As before,
last
is the previous line. In addition,f
counts the number of consecutive matches. So, we print matching lines whenf
is 2 or larger.Adding grep-like features
To emulate the
grep
output shown in the question, this version prints the filename and line number before each matching line:Awk's FILENAME variables provides the file's name and awk's
FNR
provides the line number within the file.At the beginning of each file,
FNR==1
, we resetf
to zero. This prevents the last line of one file from being considered consecutive with the first line of the next file.For those who like their code spread over multiple lines, the above looks like: