ChrisCK has asked for the wisdom of the Perl Monks concerning the following question:

I need to - Read a File

If Line contains X

Print that line and all next lines until a blank line appears

Can someone give me a good starting point for this?

I'm able to print the line that I have found X on but can't seem to get all the next lines included.

This is what I've started with-

use strict; use warnings; my $file = $ARGV[0]; open( my $fh, '<', $file ) or die "Can't open $file: $!"; while ( my $line = <$fh> ) { if ( $line =~ /X /i ) { print $line; } } close $fh;
Thanks for any help!

Replies are listed 'Best First'.
Re: How to find content between KEYWORD and BLANKLINE then print it
by 1nickt (Canon) on Jan 06, 2016 at 22:50 UTC

    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.

      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

        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.
Re: How to find content between KEYWORD and BLANKLINE then print it
by AnomalousMonk (Archbishop) on Jan 07, 2016 at 00:34 UTC
Re: How to find content between KEYWORD and BLANKLINE then print it
by edimusrex (Monk) on Jan 07, 2016 at 17:48 UTC

    I know you already have your answer but this is what I do in instances like those

    my $flag; while(<$fh>){ chomp; if (/this/) { $flag = 1; next;} elsif (/^\s*$/) {$flag = 0;} print "$_\n" if $flag; } close($fh);

    In this case it would print everything BETWEEN the line "this" (but not include that line) and would end once a blank line is found (and not include it)