Folker Naumann wrote:
Hi there! Hello,
I'm fairly new to Perl and need some help to acomplish a (simple?) task.
I extract strings from some logfiles, namely an ip-adress and bytes, by
using regexes. I use a hash to store ip-adress and associated bytes.
First i packed all logs in a temporary file but it was getting too big.
Now i'm having problems to merge the hashes from the single logfiles to
one hash for all. Either i have a hash for each of the files or just one
for the last processed file.
i should have include my code in the beginning, because i've done this
already. I know that in this case a hash is generated for every file.
But when i do the printing outside the foreach-loop just the hash of the
last file is printed. I'm aware about that problem but could not figure
out how to create only one hash for all files.
You may be able to do this by using a tied hash which will actually store the
hash's contents in a file.
perldoc DB_File
perldoc AnyDBM_File
perldoc perldbmfilter
----------------------------------------------------------
(...)
foreach $file (@sortlist){ >
open(LOG,$file) or die "Can't open $file: $!\n";
@lines = <LOG>;
foreach my $logline (reverse(@lines)) {
You could use File::ReadBackwards (which is a lot more efficient) if you
really need to this however there is no point as you are storing the data in a
hash which will not preserve the input order.
#Search for Host-IP-Adress and bytes
if( $logline =~ / (\d+\.\d+\.\d+\.\d+) \w*\/\w* (\d+) [A-Z]+/ ){
if($ipload{$1}) {$ipload{$1}+=$2}
else {$ipload{$1}=$2}
You don't need the if test as perl will do the right thing when $ipload{$1}
doesn't exist (autovivification.) You can compress the IP address quite a bit
by using Socket::inet_aton() which will also confirm that it is a valid IP
address.
}
} >
#Close log file
close(LOG) or die "Can't close $file: $!\n"; >
#Print hash sorted by Host-IP-Adress
foreach $ip ( map { $_->[0] } sort { $a->[1] <=> $b->[1] } map { [ $_,
(/(\d+)$/)[0] ] } keys %ipload) {
You don't need the list slice because without the /g (global) option the
expression can only match once. Your comment says you are sorting by IP
address but your code says you are only sorting by the last octet in the
address. Did you intend to sort by the complete IP address?
print "$ip = $ipload{$ip}\n";
} >
----------------------------------------------------------
This may work as it doesn't slurp the whole file(s) into memory:
use warnings;
use strict;
use Socket;
my %ipload;
{ local @ARGV = @sortlist;
while ( <> ) {
next unless / (\d+\.\d+\.\d+\.\d+) \w*\/\w* (\d+) [A-Z]+/
my $ip = inet_aton( $1 ) or do {
warn "$1 is an invalid IP address.\n";
next;
};
$ipload{ $1 } += $2
}
}
#Print hash sorted by Host-IP-Adress
for ( sort keys %ipload ) {
my $ip = inet_ntoa( $_ );
print "$ip = $ipload{$_}\n";
}
__END__
John
--
use Perl;
program
fulfillment