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

After a quick search, I found this very useful post made here some 3 years ago.

read lines... wait, back up?

Basically what I want to do is go line by line through my file, if I hit a specific string, take the next few lines, looking for another string. If I find the 2nd string, I'll need to check the next 10 lines or so for another string, then go BACK 1 line ahead of where I matched my first string, and start the whole process again. I've gotten up to matching the first two strings, but my SEEK always goes back to the first of the file.

It looks to me that $. doesn't give the real line number, but just counts how many lines Perl has run through. Anyways, any help is appreciated.

#!/usr/bin/perl # # use strict; use warnings; my $file = "file.log"; open ( IN, $file ) || die "Can't open $file $!"; my %position; while ( <IN> ) { chomp; $position{$.+1} = tell(IN); #I don't quite grasp this part yet # $. holds line number if ( /first_string/ ) { my $count = 0; #bad way of only finding 2nd string once print "$. $_\n"; seek IN, $position{$.+1}, 0; while ( <IN> ) { chomp; if ( ( $_ =~ /2nd_string/ ) && ( $count < 1 ) ) { print "found 2nd string\n"; $count += 1; } } } seek IN, $position{$.+1}, 0; } close FILE;
Since I can't print out $position{$.+1} I can't tell if it's seeking properly - ever. But, only the the last seek at the bottom of the file is giving me an 'unitialized value'.

Edited by castaway - changed literal html link text to an id:// link

Replies are listed 'Best First'.
Re: Problem with SEEK to go back/forward a few lines.
by pg (Canon) on Oct 16, 2003 at 02:40 UTC

    I am guessing one of the reasons that you used seek and tell, is prpobably memory concern.

    Still I suggest you to use Tie::File as Fletch already suggested. I read its entire source code before, and the author of that module actually used memory in a really wise way.

    To use it, just do something like:
    use Tie::File; my $self = tie @array, "Tie::File", "test.pl";

    The first thing pop up in your mind might be whether the whole file would be loaded into that array (and I can see that you are only interested in a small piece of the file at any given moment). The answer is NO. The array size is not only well controlled, but also configurable.

      Thanks for the info guys. It looks like Tie::File it is... I should really spend more time digging around CPAN.

      I've already started re-doing it, and it seems pretty nice.

      The file is relatively small -- no way could it consume a gig of memory.

      As for why I was using seek -- I just did a search on how to play with multiple lines, and that's what showed up.

Re: Problem with SEEK to go back/forward a few lines.
by Fletch (Bishop) on Oct 16, 2003 at 02:17 UTC

    Rather than doing the buffering and what not yourself it might be easier to use Tie::File instead.

Re: Problem with SEEK to go back/forward a few lines.
by Roger (Parson) on Oct 16, 2003 at 02:37 UTC
    How big is your log file? If not very big, you might as well load the entire file into an array with chomp(@lines = <IN>); and then you don't have to worry about remembering the position in the file. If you want any line, just dereference the array with the linenumber.

Re: Problem with SEEK to go back/forward a few lines.
by sgifford (Prior) on Oct 16, 2003 at 06:36 UTC

    Perl is probably losing track of the current line number when you seek, but since you know the correct current line number, you can tell Perl by just writing it to $. when you're done seeking around.

      >From perlvar...

        HANDLE->input_line_number(EXPR)
        $INPUT_LINE_NUMBER
        $NR
        $.      Current line number for the last filehandle accessed.
                ...
                You can adjust the counter by assigning to $., but this will
                not actually move the seek pointer.  Localizing $. will not
                localize the filehandle's line count.  Instead, it will local-
                ize perl's notion of which filehandle $. is currently aliased
                to.
      

      ...something to keep in mind.

      - parv