Today I was searching for a command online to print next two lines after a pattern and I came across an awk command which I\'m unable to understand.
$ /usr/x
Simply put the command prints a number of lines after a given regular expression expression match not including the matched line.
The number of lines is specified in the block {_=2}
and the variable _
is set to 2 if the line matches PATTERN
. Every line read after a matching line causes _
to be decremented. You can read _&&_--
as if _
is greater than zero then minus one from it, this happens for every line after a match until _
hits zero. It's quite simple when you replace the variable _
with a more sensible name like n
.
A simple demo should make it clear (print the 2 lines that follow any line matching foo
):
$ cat file
foo
1
2
3
foo
a
b
c
$ awk 'n && n--;/foo/{n=2}' file
1
2
a
b
So n
is only True when it gets set to 2 after matching a line with foo
then it decrements n
and prints the current line. Due to awk
having short circuit evaluation n
is only decrement when n
is True (n>0) so the only possible values in this case for n
are 2,1 or 0.
Awk has the following structure condition{block}
and when a condition is evaluated True then block is executed for the current record. If you don't provide a block awk
uses the default block {print $0}
so n && n--;
is a condition without a block that only evaluates to True for n
lines after the regular expression match. The semi-colon just delimits the condition n&&n--
for the conditions /foo/
make it explicit that the condition has no block.
To print the two lines following the match including the match you would do:
$ awk '/foo/{n=3} n && n--' file
foo
1
2
foo
a
b
Extra extra: the fact that the full path of /usr/xpg4/bin/awk
is used tells me this code is intended for a Solaris machine as the /usr/bin/awk
is totally broken and should be avoided at all costs.