如何在perl哈希中添加重复键中的值

  • 本文关键字:添加 perl 哈希中 perl unix
  • 更新时间 :
  • 英文 :


每周我都想通过每日日志(在红帽系统上)解析,并在IP地址列上获取一些统计信息。每日日志包含

的数据
<device>,<ip>,<city>,<packets>

这样:

样本数据 - 一条日志的前5行:

gw1,25.0.10.61,houston,50
gw1,25.0.20.61,dallas,30
gw1,25.0.30.60,ftworth,80
gw1,25.0.10.61,houston,40
gw1,25.0.10.62,houston,40

我想浏览所有七个日志,并确定每个IP地址的数据包总数。

所需的输出将为

<ip>,<packet_count>

从所有七个日志中的数据包计数排序:

25.0.10.61,480
25.0.10.62,400
25.0.30.60,220

等。

我不太确定哈希是否是这样做的最佳方法,如果是这样,则如何处理。

您可以将哈希用于数据。

代码:

my $filename ="log.txt"; #provide your filename here
open FH, $filename or die "Errorn";
my %myhash;
while(<FH>)
{
    chomp($_);
    my @arr = split(/,/, $_);
    $myhash{$arr[1]} +=$arr[3];
}
#access the hash
foreach my $ip (keys %myhash)
{
     print "$ipt$myhash{$ip}n";
}

作为单线:

perl -F, -lane '
    $count{$F[1]} += $F[3]
  } {
    while (($ip,$n) = each %count) {print "$ip,$n"}
' file*.log | sort -t, -k2,2nr

排序可以在perl中进行,但比这更长。

} {的窍门是将仅在输入末尾运行的代码分开每行应执行的代码。那个单线转化为:

BEGIN { $/ = "n"; $ = "n"; }
LINE: while (defined($_ = <ARGV>)) {
    chomp $_;
    our @F = split(/,/, $_, 0);
    $count{$F[1]} += $F[3];
}
{
    while (($ip, $c) = each %count) {
        print "$ip,$c";
    }
}

您不说如何获取日志文件的名称。该解决方案仅使用glob在当前目录中找到以.log结尾的所有文件的名称。将此列表分配给@ARGV使我们可以在没有明确打开的情况下直接读取所有文件,就像在命令行上输入了它们的名称

i保留一个hash %data,其密钥是IP地址,值是数据包计数的累积总数。我还保持宽度值$w,这是迄今为止遇到的最长IP地址的长度。这在printf中用于使列整齐地对齐

输出的顺序是在最终for环内的简单排序完成的

use strict;
use warnings 'all';
@ARGV = glob "*.log";
my %data;
my $w;
# <device>,<ip>,<city>,<packets>
while ( <> ) {
    s/s+z//;
    my ($ip, $count) = (split /,/)[1,3];
    $data{$ip} += $count;
    my $len = length $ip;
    $w = $len unless $w and $w >= $len;
}
for my $ip ( sort { $data{$b} <=> $data{$a} } keys %data ) {
    printf "%*s %dn", $w, $ip, $data{$ip};
}

输出

25.0.10.61 90
25.0.30.60 80
25.0.10.62 40
25.0.20.61 30

这是我要这样做的方法:

use strict;
use warnings;
my $packetCountByIP = {};
for (my $i = 1; $i <= 7; ++$i) {
    my $fileName = 'activity'.$i.'.log';
    my $fh;
    if (!open($fh,'<',$fileName)) { die("$fileName: $!"); }
    while (my $line = <$fh>) {
        my $fields = [split(',',$line)];
        my $ip = $fields->[1];
        my $packetCount = $fields->[3]+0;
        $packetCountByIP->{$ip} += $packetCount;
    } ## end while (log file lines)
    close($fh);
} ## end for (log files)
my $ips = [sort({$packetCountByIP->{$b}<=>$packetCountByIP->{$a}} keys(%$packetCountByIP))];
foreach my $ip (@$ips) {
    print("$ip,$packetCountByIP->{$ip}n");
} ## end foreach (ips)

最新更新