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

Hello Monks,

Second post for day!

I read thru' contents of a file one line at a time using OPEN and While; I look for a match in each line and if one matches would like to retrieve next line

Please guide me how to do this !

TIA

Then

Replies are listed 'Best First'.
Re: Getting next line after matched one
by trammell (Priest) on Dec 30, 2004 at 20:42 UTC
    Here's a not-too-subtle solution:
    my $flag = 0; while (<FILE>) { if ($flag) { $flag = 0; do_something($_); } if (/pattern/) { $flag = 1; next; } }
    You need to consider the "special" case where you have two adjacent matching lines; the logic in this code may not suffice.
      I think it is as simple as reversing the tests and using an elsif in trammell's example to cover his "special" case...

      my $flag = 0; while( <FILE> ) { if ( /test/ ) { print; $flag = 1; } elsif ( $flag ) { print; $flag = 0; } }

      --Solo

      --
      You said you wanted to be around when I made a mistake; well, this could be it, sweetheart.
Re: Getting next line after matched one
by talexb (Chancellor) on Dec 30, 2004 at 20:51 UTC

    The short answer is that you need to use $nextLine = <INPUT> to get the next line after you match, then use last to leave the loop.

    Here's something I patched together:

    #!/usr/bin/perl -w # Next After Match .. PM node 418383 my $filename = shift; open ( INPUT, $filename ) or die "Unable to open $filename: $!"; my $string = shift; my $nextLine; while(<INPUT>) { if ( /$string/ ) { $nextLine = <INPUT>; last; } } close ( INPUT ); if ( defined ( $nextLine ) ) { print "INFO: $string found in file $filename, next line is:\n"; print $nextLine; } else { print "INFO: $string not found in file $filename.\n"; }
    When I run it on itself I get the following:
    [foo@bar dev]$ perl -w nam.pl nam.pl print INFO: print found in file nam.pl, next line is: print $nextLine; [foo@bar dev]$ perl -w nam.pl nam.pl whoosat INFO: whoosat not found in file nam.pl.
    Seems to work.

    Alex / talexb / Toronto

    "Groklaw is the open-source mentality applied to legal research" ~ Linus Torvalds

Re: Getting next line after matched one
by rnahi (Curate) on Dec 30, 2004 at 20:58 UTC

    The one-liner approach:

    $ cat input.txt one two three four five six seven $ perl -ne 'print $_ = <> and last if /five/' input.txt six
Re: Getting next line after matched one
by superfrink (Curate) on Dec 30, 2004 at 20:49 UTC
    As you loop through the input lines just set a flag where you need to. Then when you get to the next line do whatever you need to. You might also want a check at the end of the loop to see if your input didn't end properly.
    #!/usr/bin/perl -w use strict; my $line; my $pattern = "asdf"; my $flag = 0; while($line = <>) { if($flag) { print "do something here to $line \n"; } if($line =~ m/$pattern/) { $flag = 1; } else { $flag = 0; } } if($flag) { print "Oops, we don't have a line to work on but flag was set.\n"; }
Re: Getting next line after matched one
by Eimi Metamorphoumai (Deacon) on Dec 30, 2004 at 20:51 UTC
    If you don't have to worry about consecutive lines, you could just read and print the next line.
    while (<FILE>){ if (/text to check for/){ my $nextline = <FILE>; print $nextline; } }
    (or simply print scalar(<FILE>);)
Re: Getting next line after matched one
by sgifford (Prior) on Dec 30, 2004 at 20:44 UTC
    The basic technique is to read each line from the file, maintaining a flag called something like lastmatched. If lastmatched is set, print the current line. If the current line matches the pattern, set the lastmatched flag; otherwise clear it.

      my question was : once a line is matched, what should I do , like increment pointer to go to next line to get that line in file ?

      I think previous two posts were talking about setting flags if match is found !

        The previous posts do go to the next line, the flag is set so that when you get to the next line, you know that the previous line was a match. If you get to a line, and the flag is set, then do whatever it is that you wanted to do after finding the matching line.
        UPDATE-
        I'm going to use tremmel's code to make sure that you understand what is going on, forgive me if I go in to too much detail, but I don't know where your level of understanding is - not trying to talk down to you, I'm a relative beginner myself.
        my $flag = 0; while (<FILE>) { #If not at end of file process next line if ($flag) { #flag is set, previous line was a match $flag = 0; #reset the flag do_something($_); #do what you want to do after finding match } if (/pattern/) { #if this line matches $flag = 1; #set the flag so I can do something on next line next; #go to next line, not required but might make more read +able } }
        Basically, whenever you evaluate <FOO> in scalar context, it reads the next line from the file handle FOO and returns it, or returns undef if you're at the end of the file. A normal
        while (<FOO>){
        loop is short for
        while (defined($_ = <FOO>)){
        So all you have to do to read the next line is execute <FOO> again, either by doing so directly and using the result, or by waiting for the next iteration of the loop (which will read it for you) and then dealing with it then (the flag, then, lets you know that last time you saw what you needed). Which is preferable depends on what else you need to do with what lines in the file.
        The problem with the approach you describe is that it won't work if two lines in a row match. For example, say you have a file like:
        foo
        bar
        barbar
        bell
        
        and the pattern is /bar/. bar will match; if you read in the next line and print it out, you won't notice that barbar also matches, and so won't print out bell. You could add some code to fix this, but the flag approach handles it quite nicely.
Re: Getting next line after matched one
by Anonymous Monk on Dec 31, 2004 at 12:00 UTC
    perl -ne 'print if $,;$, = /PATTERN/' input
    Note that this also works if you have two (or more) consecutive lines matching PATTERN - it prints all of them except the first, and the line following it. It won't try to read past eof either.
      Is there any advantage to using $, here besides an obscurity bonus? :)
Re: Getting next line after matched one
by Solo (Deacon) on Dec 30, 2004 at 20:55 UTC
    Now that's a post storm... man, can't turn your back for 5 mins... ;p

    --Solo