http://www.perlmonks.org?node_id=181068

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

Using the while (<>) construction takes a file from the command line and parses each individual line of the file (up to the \n). How do I 'peek' at the next line in the file without losing my current place? Doing something like:

my $nextLine = <>

would skip the current line, but all I want to do is check the next line for before processing the current line.

I have written all sorts of convoluted test code, trying to fiddle with line numbers, the @ARGV array, the $_ variable, but nothing has worked so far.

Many thanks for your help.

Replies are listed 'Best First'.
Re: How to 'peek' at next line while parsing with <>
by japhy (Canon) on Jul 11, 2002 at 16:57 UTC
    Well, you can always use redo()...
    while ($line = <>) { # redo comes HERE # do something my $next = <>; if ($next !~ /^#/) { # if the next line DOES NOT start with a "#" # reuse it and restart this iteration of the loop $line = $next; redo; } }
    Or you can use seek() and tell() to make Perl think nothing ever happened:
    while ($line = <>) { # ... my $pos = tell ARGV; my $next = <>; seek ARGV, $pos, 0; # ... }

    _____________________________________________________
    Jeff[japhy]Pinyan: Perl, regex, and perl hacker, who'd like a job (NYC-area)
    s++=END;++y(;-P)}y js++=;shajsj<++y(p-q)}?print:??;

Re: How to 'peek' at next line while parsing with <>
by Abigail-II (Bishop) on Jul 11, 2002 at 17:14 UTC
    You cannot in general. With non-seekable handles (pipes, STDIN, sockets, fifo, etc) you can't seek back, and usually you can't put something back in the stream either.

    But you can use a buffer. The simplest is a one-scalar buffer. If you want to look, read in the line in a scalar, later, if you want to process the line, process the scalar. You can wrap this up in a module, and if you want to be fancy, you tie it to a filehandle. Or with perl 5.8, you should be able to write an IO layer that does that for you.

    Abigail

Re: How to 'peek' at next line while parsing with <>
by talexb (Chancellor) on Jul 11, 2002 at 16:59 UTC
    Depending on the size of the input file, you could
    1. Read the file into an array if the file is not too large; or
    2. Arrange to pretend that the current line from the diamond operator is the 'next' line and the last line is the 'current' line.

    --t. alex

    "Mud, mud, glorious mud. Nothing quite like it for cooling the blood!" --Michael Flanders and Donald Swann

      Number two was also what I had in mind. Something like the following:

      #! /usr/bin/perl use strict ; use warnings ; my $line = <> ; my $queued_line = '' ; chomp $line ; while ( $queued_line = <> ) { chomp $queued_line ; $line =~ m|<(.+?)>| ; print "Found match: [$1] (next line: $queued_line)\n" ; $line = $queued_line ; } $line =~ m|<(.+?)>| ; print "Found match: [$1] (last line)\n" ;

      _______________
      D a m n D i r t y A p e
      Home Node | Email
Re: How to 'peek' at next line while parsing with <>
by BrowserUk (Patriarch) on Jul 11, 2002 at 17:08 UTC

    This will do what you want - I'm using <DATA> for test purposes. use <> for yours.

    #!perl -w use strict; while (<DATA>) { chomp; print "current line=$_\n"; if (/check next/) { my $pos = tell(); my $testline = <DATA>; chomp $testline; print "'next line' = $testline\n"; #do something... seek DATA, $pos, 0; } print "current line=$_\n"; } __DATA__ line 1 line 2 line 3 check next line 4 OK? line 5

    Anyone know of an abbottoire going cheap?

Re: How to 'peek' at next line while parsing with <>
by particle (Vicar) on Jul 11, 2002 at 18:38 UTC
    here's a buffered method:

    #!/usr/bin/perl use strict; use warnings; { $_ = <DATA>; my $next_line; while( $next_line = <DATA> ) { print "current line: $_ -- next line: $next_line$/"; } continue { $_ = $next_line; } } __DATA__ 1 2 3 4 5
    yeilds:

    current line: 1 -- next line: 2 current line: 2 -- next line: 3 current line: 3 -- next line: 4 current line: 4 -- next line: 5
    note: the last line is not processed.

    ~Particle *accelerates*

Re: How to 'peek' at next line while parsing with <>
by TexasTess (Beadle) on Jul 11, 2002 at 18:45 UTC
    Why not just read it into a $scalar variable for checking before assigning it where you really want it to go if it meets the conditions....?

    TexasTess
    "Great Spirits Often Encounter Violent Opposition From Mediocre Minds" --Albert Einstein