in reply to Re: Regex question
in thread Regex question

The way to do this is to define an END{} block.

With the -n or -p switch, there's another solution - Abigail's trick, the 'eskimo greeting':

perl -ne '}{ print $.' # count lines

My solution made into a one-liner

perl -ne 'BEGIN{$_=shift for$B,$A,$p}/$p/and@l=(),do{<>for 1..$A},next +;push@l,$_;print shift@l if$B<@l}{print@l' 3 5 pattern test.txt

where 3 is lines before, 5 is lines after the pattern.

Run through B::Deparse

sub BEGIN { ($_ = shift(@ARGV)) foreach (($B, $A, $p)); } LINE: while (defined(($_ = <ARGV>))) { (/pat/ and ((@l = ()), do { <ARGV> foreach (1 .. $A) }, next)); push(@l, $_); (($B < @l) and print(shift(@l))); } { print(@l); }
Sample data:
keep 1 keep 2 keep 3 keep 4 delete 1 delete 2 delete 3 pattern delete 1 delete 2 delete 3 delete 4 delete 5 keep 5 keep 6 keep 7 keep 8 keep 9 keep 10 keep 11 delete 1 delete 2 delete 3 pattern delete 1 delete 2 delete 3 delete 4 delete 5 keep 12 keep 13 keep 14 keep 15 delete 1 delete 2 delete 3 pattern delete 1 delete 2 delete 3 delete 4 delete 5 keep 16 keep 17 keep 18 keep 19 delete 1 delete 2 delete 3 pattern delete 1 delete 2 delete 3 delete 4 delete 5 keep 20 keep 21
Output:
keep 1 keep 2 keep 3 keep 4 keep 5 keep 6 keep 7 keep 8 keep 9 keep 10 keep 11 keep 12 keep 13 keep 14 keep 15 keep 16 keep 17 keep 18 keep 19 keep 20 keep 21