Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

One-liner to print all lines between two patterns

Using one line of Perl code, what is the shortest way possible to print all the lines between two patterns not including the lines with the patterns?

If this is file.txt:

aaa
START
bbb
ccc
ddd
END
eee
fff

I want to print this:

bbb
ccc
ddd

I can get most of the way there using something like this:

perl -ne 'print if (/^START/../^END/);'

That includes the START and END lines, though.

I can get the job done like this:

perl -ne 'if (/^START/../^END/) { print unless (/^(START)|(END)/); };' file.txt

But that seems redundant.

What I'd really like to do is use lookbehind and lookahead assertions like this:

perl -ne 'print if (/^(?<=START)/../(?=END)/);' file.txt

But that doesn't work and I think I've got something just a little bit wrong in my regex.

These are just some of the variations I've tried that produce no output:

perl -ne 'print if (/^(?<=START)/../^.*$(?=END)/);' file.txt
perl -ne 'print if (/^(?<=START)/../^.*(?=END)/);' file.txt
perl -ne 'print if (/^(?<=START)/../(?=END)/);' file.txt
perl -ne 'print if (/^(?<=START)/../.*(?=END)/);' file.txt
perl -ne 'print if (/^(?<=START)/../^.*(?=END)/);' file.txt
perl -ne 'print if (/^(?<=START)/../$(?=END)/);' file.txt
perl -ne 'print if (/^(?<=START)/../^(?=END)/);' file.txt
perl -ne 'print if (/^(?<=START)/../(?=^END)/);' file.txt
perl -ne 'print if (/^(?<=START)/../.*(?=END)/s);' file.txt
like image 672
Vince Avatar asked Nov 16 '25 06:11

Vince


2 Answers

Read the whole file, match, and print.

perl -0777 -e 'print <> =~ /START.*?\n(.*?)END.*?/gs;' file.txt

May drop .*? after START|END if alone on line. Then drop \n for a blank line between segments.


Read file, split line by START|END, print every odd of @F

perl -0777 -F"START|END" -ane 'print @F[ grep { $_ & 1 } (0..$#F) ]' file.txt

Use END { } block for extra processing. Uses }{ for END { }.

perl -ne 'push @r, $_ if (/^START/../^END/); }{ print "@r[1..$#r-1]"' file.txt

Works as it stands only for a single such segment in the file.

like image 72
zdim Avatar answered Nov 17 '25 22:11

zdim


It seems kind of arbitrary to place a single-line restriction on this, but here's one way to do it:

$ perl -wne 'last if /^END/; print if $p; $p = 1 if /^START/;' file.txt
like image 32
Matt Jacob Avatar answered Nov 17 '25 20:11

Matt Jacob



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!