olibre olibre - 2 months ago 19
Perl Question

Print the smallest set of lines between two patterns (BEGIN and END) including the lines of these two patterns

Input file



aaa
Any--END--Pattern
bbb
ANY--BEGIN--PATTERN
ccc # do not print
ANY--BEGIN--PATTERN # print 1
ddd # print 2
Any--END--Pattern # print 3
eee
fff
ANY--BEGIN--PATTERN # print 4
ggg # print 5
Any--END--Pattern # print 6
hhh # print 7
Any--END--Pattern # print 8
iii # do not print
ANY--BEGIN--PATTERN
jjj


Wanted output



ANY--BEGIN--PATTERN # print 1
ddd # print 2
Any--END--Pattern # print 3
ANY--BEGIN--PATTERN # print 4
ggg # print 5
Any--END--Pattern # print 6
hhh # print 7
Any--END--Pattern # print


Notes




  • Print from the latest
    ANY--BEGIN--PATTERN
    before the current
    Any--END--Pattern
    .

  • Print until the last
    Any--END--Pattern
    if no
    ANY--BEGIN--PATTERN
    meet.



The solution should be a tiny command line using tools available on many systems: , , , ...

Many similar questions but cannot find an answer for this issue





The answers I have tested from these questions print the line
ccc
and/or the line
iii
. My several attempts have this same drawback.

I think there is an elegant one-line command solving this issue but I cannot find it. I could write a ten lines script, but I wonder what are the
sed
or
awk
or
...
tricks to do it ???

123 123
Answer

This should work with sed

sed '$b1;/BEGIN/{:1;x;s/\(BEGIN.*END[^\n]*\).*/\1/;t;x;h};H;d' file
Comments