Ubuntu – awk: print only lines that come after specific guard line pattern

awkcommand line

Consider this file:

#!/usr/bin/env bash
cat > example_file.txt <<EOL
|dms,wew,qwqw|
|m|head1|
|3,4,6|
|3e,2,23|
|m|head2|
|xw,12,2123|
|23,d,213|
|23,22q,2skl|
|m|head1|
|dljs,wqpw,2;a|
|dllw,w1p,1q;a|
EOL

Every once in a while, there will be a
guard pattern: a line that starts with:

|m|

(yes, the first line of the file need not
be a guard pattern)
Now I only want to print those lines
for which the last guard pattern was:

|m|head1|

and ignore all other lines.
In other worst, I would like the output to be:

#!/usr/bin/env bash
cat > desired_result_file.txt <<EOL
|m|head1|
|3,4,6|
|3e,2,23|
|m|head1|
|dljs,wqpw,2;a|
|dllw,w1p,1q;a|
EOL

Best Answer

Regex-oriented

$ awk '/^\|m\|/ {/\|head1\|/ ? p=1 : p=0} p' example_file.txt 
|m|head1|
|3,4,6|
|3e,2,23|
|m|head1|
|dljs,wqpw,2;a|
|dllw,w1p,1q;a|

or field-oriented

$ awk -F'|' '$2 == "m" {$3 == "head1" ? p=1 : p=0} p' example_file.txt 
|m|head1|
|3,4,6|
|3e,2,23|
|m|head1|
|dljs,wqpw,2;a|
|dllw,w1p,1q;a|

p is effectively a print flag.

Awk programs consist of pattern {action} pairs, in which action is executed on a record if pattern evaluates true (non-zero). You can omit pattern - in which case {action} is evaluated for every record - or omit {action} in which case awk applies the default pattern, which is to print the record: the latter is what's happening here.