in reply to How to find content between KEYWORD and BLANKLINE then print it

You can use the range operator (aka flip-flop):

while ( <$fh> ) { print if /X/ .. /^\s*$/ and not /^\s*$/; }

Edit: updated to fix a precedence problem with if ( $line =~ /X/i .. /^\s*$/ ), thanks Eily!


The way forward always starts with a minimal test.

Replies are listed 'Best First'.
Re^2: How to find content between KEYWORD and BLANKLINE then print it
by Eily (Monsignor) on Jan 06, 2016 at 23:37 UTC

    I'll ++ your post as soon as I get votes. It still contains a mistake though. Since =~ is of higher precedence than .., your code is actually parsed as ($line =~ /X/i) .. /^\s*$/ which means the second regex will be applied on $_. Adding parentheses like this: $str =~ (/A/../B/) won't work either because this will apply the regular expressions first, on $_ (and this also happens to be the range operator, not flip flop).

    Here, using the default variable $_ is the best option for readability:

    while (<DATA>) { if (/A/../B/) { print; } } __DATA__ 1 2 A 3 4 B 5 6

      The wording of the OP seems to imply that the blank line that ends the range should not actually be printed, as 1nickt attempts. Adding another && condition after the flip-flop achieves that.

      $ perl -Mstrict -Mwarnings -E ' open my $inFH, q{<}, \ <<EOD or die $!; Seb Xavier Peter Roland Jim Xerox Paddle Yoyo EOD while ( <$inFH> ) { print if ( m{X} .. m{^\s*$} ) && ! m{^\s*$}; }' Xavier Peter Xerox Paddle $

      I hope this is of interest.

      Cheers,

      JohnGG

        As documented in perlop, the flip-flop operator appends E0 to its return value for the last line, so you can exclude it directly by inspecting the value:
        while (<>) { my $m = /X/ .. /^\s*$/; print if $m && $m !~ /E0$/; }
        ($q=q:Sq=~/;[c](.)(.)/;chr(-||-|5+lengthSq)`"S|oS2"`map{chr |+ord }map{substrSq`S_+|`|}3E|-|`7**2-3:)=~y+S|`+$1,++print+eval$q,q,a,
      Thank you both very much!

      This is what ended up working perfectly-

      use strict; use warnings; my $file = $ARGV[0]; open( my $fh, '<', $file ) or die "Can't open $file: $!"; while ( <$fh> ) { if ( /Error:/i .. /^\s*$/ ) { print; } } close $fh;
      Error: was my keyword and I wanted all of the error message below it until a blank line was found.

      Thanks again!

      Thanks for the correction. I was hewing as closely as possible to the OP's code and didn't test before posting; I guess I've always used it with $_. Updated and noted in my reply.


      The way forward always starts with a minimal test.

        You can still use a lexical but you have to be explicit about what is being matched, also taking care with the difference in precedence of and and &&. With lower precedence and:-

        $ perl -Mstrict -Mwarnings -E ' open my $inFH, q{<}, \ <<EOD or die $!; Seb Xavier Peter Roland Jim Xerox Paddle Yoyo EOD while ( my $line = <$inFH> ) { print $line if $line =~ m{X} .. $line =~ m{^\s*$} and $line !~ m{^\s*$}; }' Xavier Peter Xerox Paddle $

        Higher precedence && requires parentheses:-

        $ perl -Mstrict -Mwarnings -E ' open my $inFH, q{<}, \ <<EOD or die $!; Seb Xavier Peter Roland Jim Xerox Paddle Yoyo EOD while ( my $line = <$inFH> ) { print $line if ( $line =~ m{X} .. $line =~ m{^\s*$} ) && $line !~ m{^\s*$}; }' Xavier Peter Xerox Paddle $

        Cheers,

        JohnGG