Issue
Need to print lines after the last match to the end of file. The number of matches could be anything and not definite. I have some text as shown below.
MARKER
aaa
bbb
ccc
MARKER
ddd
eee
fff
MARKER
ggg
hhh
iii
MARKER
jjj
kkk
lll
Output desired is
jjj
kkk
lll
Do I use awk with RS and FS to get the desired output?
Solution
You can actually do it with awk
(gawk) without using any pipe.
$ awk -v RS='(^|\n)MARKER\n' 'END{printf "%s", $0}' file
jjj
kkk
lll
Explanations:
- You define your record separator as
(^|\n)MARKER\n
viaRS='(^|\n)MARKER\n'
, by default it is theEOL
char 'END{printf "%s", $0}'
=> at the end of the file, you print the whole line, asRS
is set at(^|\n)MARKER\n
,$0
will include all the lines until EOF.
Another option is to use
grep
(GNU):
$ grep -zoP '(?<=MARKER\n)(?:(?!MARKER)[^\0])+\Z' file
jjj
kkk
lll
Explanations:
-z
to use the ASCII NUL character as delimiter-o
to print only the matching-P
to activate the perl mode- PCRE regex:
(?<=MARKER\n)(?:(?!MARKER)[^\0])+\Z
explained here https://regex101.com/r/RpQBUV/2/
Last but not least, the following
sed
approach can also been used:
sed -n '/^MARKER$/{n;h;b};H;${x;p}' file
jjj
kkk
lll
Explanations:
n
jump to next lineh
replace the hold space with the current lineH
do the same but instead of replacing, append${x;p}
at the end of the file exchange (x
) hold space and pattern space and print (p
)
that can be turned into:
tac file | sed -n '/^MARKER$/q;p' | tac
if we use tac
.
Answered By - Allan Answer Checked By - David Marino (WPSolving Volunteer)