in reply to Interlaced log parser

I would try to process the log files in a single pass. You don't give a sufficient sample of your log files to be certain, but perhaps something like the following would work.

use strict; use warnings; my %transaction; foreach my $file (<*.log>) { open(my $fh, '<', $file) or die "$file: $!"; while(<$fh>) { chomp; if(/(.*?) \(([^\)]+)\)(.*)/) { my ($timestamp, $id, $log) = ($1, $2, $3); push(@{$transaction{$id}}, [ $timestamp, $id, $log, $file, + $. ]); my $status = status($transaction{$id}); if($status eq 'complete') { submit($transaction{$id}); delete($transaction{$id}); } elsif($status eq 'corrupt') { report($status, $transaction{$id}); delete($transaction{$id}); } } else { warn "invalid input line: $_"; } } close($fh); } foreach my $id (keys %transaction) { report('incomplete', $transaction{$id}); } exit(0); sub status { my $transaction = shift; return('incomplete') if(@$transaction < 3); return('corrupt') if( @$transaction > 3 or $transaction->[0][2] !~ /^(Authentication Request|Authenticati +on Response|Accounting Request)/ or $transaction->[1][2] !~ /^Acct-Session-Id :/ or $transaction->[2][2] !~ /^User-Name :/ ); return('complete'); } sub submit { my $transaction = shift; print "submit to database\n"; foreach my $line (@$transaction) { my ($timestamp, $id, $log, $file, $line) = @$line; print "\t$file line $line: $timestamp ($id)$log\n"; } } sub report { my ($status, $transaction) = @_; print STDERR "ERROR: $status transaction\n"; foreach my $line (@$transaction) { my ($timestamp, $id, $log, $file, $line) = @$line; print STDERR "\t$file line $line: $timestamp ($id)$log\n"; } }