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

--
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]
<http://learn.perl.org/> <http://learn.perl.org/first-response>




Reply via email to