Printing with sed or awk a line following a matching pattern

awk, sed

Solution

Never use the word "pattern" in this context as it is ambiguous. Always use "string" or "regexp" (or in shell "globbing pattern"), whichever it is you really mean. See How do I find the text that matches a pattern? for more about that.

The specific answer you want is:

awk 'f{print;f=0} /regexp/{f=1}' file

or specializing the more general solution of the Nth record after a regexp (idiom "c" below):

awk 'c&&!--c; /regexp/{c=1}' file

The following idioms describe how to select a range of records given a specific regexp to match:

a) Print all records from some regexp:

awk '/regexp/{f=1}f' file

b) Print all records after some regexp:

awk 'f;/regexp/{f=1}' file

c) Print the Nth record after some regexp:

awk 'c&&!--c;/regexp/{c=N}' file

d) Print every record except the Nth record after some regexp:

awk 'c&&!--c{next}/regexp/{c=N}1' file

e) Print the N records after some regexp:

awk 'c&&c--;/regexp/{c=N}' file

f) Print every record except the N records after some regexp:

awk 'c&&c--{next}/regexp/{c=N}1' file

g) Print the N records from some regexp:

awk '/regexp/{c=N}c&&c--' file

I changed the variable name from "f" for "found" to "c" for "count" where appropriate as that's more expressive of what the variable actually IS.

`f` is short for `found`. Its a boolean flag that I'm setting to 1 (true) when I find a string matching the regular expression regexp in the input (`/regexp/{f=1}`). The other place you see `f` on its own in each script it's being tested as a condition and when true causes awk to execute its default action of printing the current record. So input records only get output after we see regexp and set `f` to 1/true.

`c && c-- { foo }` means "if `c` is non-zero then decrement it and if it's still non-zero then execute `foo`" so if `c` starts at 3 then it'll be decremented to 2 and then `foo` executed, and on the next input line `c` is now 2 so it'll be decremented to 1 and then `foo` executed again, and on the next input line `c` is now 1 so it'll be decremented to 0 but this time `foo` will not be executed because 0 is a false condition. We do `c && c--` instead of just testing for `c-- > 0` so we can't run into a case with a huge input file where `c` hits zero and continues getting decremented so often it wraps around and becomes positive again.

Problem

Question: I'd like to print a single line directly following a line that contains a matching pattern. My version of `sed` will not take the following syntax (it bombs out on `+1p`) which would seem like a simple solution: ``` sed -n '/ABC/,+1p' infile ``` I assume `awk` would be better to do multiline processing, but I am not sure how to do it.

Original source

Related problems