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

hello gurus,
I am trying to see when I read a file, I want to print next line after the pattern is found
But my code is wrong. I am wondering how to easily do this in perl
use warnings; use strict; my $file = '/tmp/test_file'; open FF, $file , or die "you suck\n"; while (<FF>) { next unless /XXXX/; $. += 1; ### obviously this does not work ... print $_ ; } close (FF);
ZZZZZZZZZZZZ YYYYY XXXX XX XXXX 3333 ii XXXX asdfddd
and output should be
XX 3333 asdfddd

Replies are listed 'Best First'.
Re: how to print next line after the pattern in perl
by moritz (Cardinal) on Jun 09, 2010 at 19:05 UTC

    Low-tech solution which just uses a variable to indicate if the next line should be printed:

    use warnings; use strict; my $print_next; while (<DATA>) { print if $print_next; $print_next = /XXXX/; } __DATA__ ZZZZZZZZZZZZ YYYYY XXXX XX XXXX 3333 ii XXXX asdfddd
    Perl 6 - links to (nearly) everything that is Perl 6.
Re: how to next line after the pattern in perl
by ambrus (Abbot) on Jun 09, 2010 at 19:30 UTC

    I prefer moritz's solution (while (<>) { $f and print; $f = /XXXX/; }) to lidden's, because it works well even if the pattern matches two consecutive lines.

    See also my cgrep: Egrep clone with function name display for something similar, it can do context grep, that is, print a number of lines after and before a line matching a pattern.

Re: how to next line after the pattern in perl
by kennethk (Abbot) on Jun 09, 2010 at 19:05 UTC
    One fairly straight-forward way to accomplish this task would be to simply read and print the next line in the file:

    while (<FF>) { next unless /XXXX/; print scalar <FF>; }

    Note that scalar is required to turn the print statement into scalar context. There are other ways of accomplishing this (e.g. appending an empty string), but this is simple and clear, at least to me. Note that this is fragile in that it would miss consecutive lines.

      print scalar <FF>; ...worked for me - I needed the 2nd and 3rd lines after a match, so I used it twice.
Re: how to next line after the pattern in perl
by toolic (Bishop) on Jun 09, 2010 at 19:07 UTC
    A simple state machine will work:
    use strict; use warnings; my $flag = 0; while (<DATA>) { if (/XXXX/) { $flag = 1; } elsif ($flag) { print; $flag = 0; } } __DATA__ ZZZZZZZZZZZZ YYYYY XXXX XX XXXX 3333 ii XXXX asdfddd
      And a version that will catch consecutive lines and is shorter. Shorter is always better, right?

      use strict; use warnings; my $flag = 0; while (<DATA>) { print if $flag; $flag = /XXXX/; } __DATA__ ZZZZZZZZZZZZ YYYYY XXXX XX XXXX 3333 ii XXXX asdfddd

      Correct, but fundamentally a repeat of Re: how to print next line after the pattern in perl.

        "...catch consecutive lines...?
        and
        Correct but fundamentally....

        Interesting proposition which points up a (possible) ambiguity or shortcoming in the original problem statement: What should be done when a second consecutive matching line exists?

        • Print it and the following line? (which yours does)
        • Print just the non-matching line?
        • Something else?

        Update: Fixed punct at the end of the first li from "?" to ")"
        while LOL at kennethk's reply

Re: how to next line after the pattern in perl
by zwon (Abbot) on Jun 09, 2010 at 19:06 UTC
Re: how to next line after the pattern in perl
by Anonymous Monk on Jun 09, 2010 at 19:52 UTC
    Thank you All!!
    It is quite simple yet I didn't get the concept but w/ your explanation and actual code, it is quite clear
Re: how to next line after the pattern in perl
by lidden (Curate) on Jun 09, 2010 at 19:04 UTC
    Change:
    while (<FF>) { next unless /XXXX/; $. += 1; ### obviously this does not work ... print $_ ; }
    To:
    while (<FF>) { next unless /XXXX/; print <FF>; }
    and it should work. (not tested)

    Update: it does not work, prints way too much, see moritz and kennethk below.

      print <FF>; executes the <...> aka readline in list context, and thus prints all the remaining lines in the file.

      Adding a scalar after the print should solve that problem.

      Perl 6 - links to (nearly) everything that is Perl 6.

      Not quite, lidden, as yours (modified solely to use __DATA__ rather than a file, prints the matching string (not sought by OP), as well as the line thereafter.

      perl 843893.pl XX XXXX 3333 ii XXXX asdfddd

      Testing pays off.

      Update: See moritz' diagnosis and Rx, above.

Re: how to next line after the pattern in perl
by BioLion (Curate) on Jun 10, 2010 at 12:39 UTC

    All a bit late now, but another way to do it could be to buffer the reading in of the file ( a la Re: Grabbing lines three-by-three from a file ). This way you could read lines in pairs, testing the first and printing the second. Not that the solutions above need improving, but TIMTOWTDI and all that...

    Just a something something...