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

I have one file where I use the substr to get out all the id's and push them into an array.

I then open the log file and find the line that the id shows up on, but I actually want the next line to be the message that goes into the OUTFILE.

I think the problem is with the foreach loop as I am getting an error.

Error: Use of uninitialized value in pattern match (m//) at ./amp_parse.pl line 39,
use strict; use warnings; my $IDFILE = 'H_E'; my $AMPFILE = 'a.log'; my $OUTFILE = 'report.lst'; my @id_hits; # loop through the id file to get the prime id from each line and # push it onto the @hits array # open my $IFILE, '<', $IDFILE or die "Could not open $IDFILE: $!"; my @id_hits=map substr($_, 0, 6), <$IFILE>; #print "@id_hits"; # loop through the amp.log find the line matches for the hits in # this @id_hits array. # open my $AFILE, '<', $AMPFILE or die "Could not open $AMPFILE: $!"; my ( $line, $next_line ); my @log = <$AFILE>; while ( @log ) { foreach my $prime_id ( @id_hits ) { $line = shift @log until $line =~ /$prime_id/; undef $line; $next_line = shift @log until $next_line =~ /^AMP-commit/; my $amp_msg = $next_line; undef $next_line; open my $OFILE, '>', $OUTFILE or die "Cannot create report fil +e: $!"; print $OFILE "$prime_id:\t$amp_msg\n" or die "Cannot print to +file: $!"; close $OFILE; } }

Any help and suggestions?

Robert

Replies are listed 'Best First'.
Re: Search a file with ids from another file
by blazar (Canon) on May 07, 2007 at 19:14 UTC

    Side notes:

    open my $IFILE, '<', $IDFILE || die "Could not open $IDFILE: $!";

    This does not do what you think it does. General rule is: use high precedence logical operators to act on values, low precedence ones for flow control. Otherwise, do not omit parens.

    while ( my $ifile_line = <$IFILE> ) { my $hits = substr($ifile_line, 0, 6); push @id_hits, $hits; }

    FWIW, this is one of those cases in which slurping is ok:

    my @id_hits=map substr($_, 0, 6), <$IFILE>;
      Thanks for the hints!
Re: Search a file with ids from another file
by Not_a_Number (Prior) on May 07, 2007 at 19:57 UTC

    Apart from the comments made above, I would suggest two things:

    1) In your last while loop, you attempt to open and close a filehandle each time you come upon a match. This is highly inefficient. Open $OFILE before the loop, and close it after.

    2) It would no doubt be better (or at least more elegant) to turn your @id_hits into a single regex, rather than looping through the array inside another loop. One simple way of doing this would be to add a line:

    my $id_regex = join '|', @id_hits;

    after the first while loop, but you could most likely create a more efficient regex if you used Regexp::Assemble

    Putting that all together would give something like:

    use strict; use warnings; use Regexp::Assemble; my $id_regex = Regexp::Assemble->new; my $IDFILE = ...; # Your filenames here open my $ifh, '<', $IDFILE or die "Could not open $IDFILE: $!"; while ( my $line = <$ifh> ) { $id_regex->add( substr $line, 0, 6 ); } close $ifh; open my $afh, '<', $AMPFILE or die "Could not open $AMPFILE: $!"; open my $ofh, '>', $OUTFILE or die "Could not open $OUTFILE: $!"; while ( my $line = <$afh> ) { chomp $line; if ( $line =~ $id_regex ) { my $next = <$afh>; print $ofh $line, "\t", $next if $next =~ /^Amp-commit/; } } close $ofh; close $afh;

    Untested, unfortunately, as I don't have access to your data files...

    Belated update (sorry!): changed

        my $next = <DATA>;

    to

        my $next = <$afh>;
Re: Search a file with ids from another file
by RL (Monk) on May 07, 2007 at 18:07 UTC

    Hi,

    foreach my $prime_id ( @id_hits ) { $line = shift @log until $line =~ /$prime_id/;

    you're shifting elements off @log on the first run.
    @log gets shortened this way.

    Think of the first $prime_id not found in the logfile at all this will result in @log being empty on the second run of the foreach loop. Did you consider this?

    I'm not sure about the structure of $prime_id's in relation to the logfile's content but it may result in some unpredictable results.

    Hope this helps.
    RL

      I had not...bf on my part.

      @id_hits looks like this:

      G81432 G81765 H43121

      And more like that...

      So I want to loop through the log for each one of those, find it and capture the "next" line after it.

        So I want to loop through the log for each one of those, find it and capture the "next" line after it.

        Are the lines which can match the ids in the same order as the ids? To each id does correspond a unique matching line? How many are the ids? (This can make a difference - since you print them, I suppose they're not too many.) Are they all in this form? (i.e. a capital letter followed by five numbers.) Can the "next" line also match one id, or is this impossible a priori?

Re: Search a file with ids from another file
by Moron (Curate) on May 07, 2007 at 18:24 UTC
    The only explanation I can think of is that the logfile exhausts before the hits do. Because, for this not to be the case, an extremely special relationship would have to exist between the ids in the two files, i.e. a bijective mapping would have to exist and the ordering would have to be the same. Can we see the first 10 ids-worth of each file?
    __________________________________________________________________________________

    ^M Free your mind!