2020年5月19日火曜日

Perl で多次元のhash(連想配列)を使う


こんにちは

突然ですが、Perl で多次元のhash(連想配列)を使う方法です。なぜ急にこんなことを書き出したかというと、いままでいざやろうとすると「あれ?」といつもなるので覚書的に書いておこうかと思いました。

例えばこんなCSVがあったとします。

2020/05/02,10.10.11.1,telnet,net1
2020/05/02,10.10.12.1,telnet,net2
2020/05/02,10.10.11.1,telnet,net1
2020/05/02,10.10.11.1,ftp,net1
2020/05/02,10.10.12.1,telnet,net2
2020/05/02,10.10.11.1,telnet,net1
2020/05/02,10.10.11.1,telnet,net1

これをユニークにするとこんな感じになると思います。

2020/05/02,10.10.11.1,telnet,net1
2020/05/02,10.10.11.1,ftp,net1
2020/05/02,10.10.12.1,telnet,net2

この処理をhash(連想配列)を使ってやってみます。
こんな感じです。hash.pl という名前で保存します。


my %access;
my $line_tmp;
my @access_log;

my $date;
my $ip;
my $port;
my $net;


open (FH_TARGET, "<log.txt") or die "can't open file log.txt";
while ( $line_tmp = <FH_TARGET> ){
    @access_log = split(/,/, $line_tmp);
    $date = $access_log[0];
    $ip  = $access_log[1];
    $port = $access_log[2];
    $net = $access_log[3];
    chomp($date);
    chomp($ip);
    chomp($port);
    chomp($net);
    $access{$date}{$ip}{$port}{$net} +=1 ; 
}

foreach $date ( sort keys %access ){
    foreach $ip ( sort keys %{$access{$date}} ) {
        foreach $port ( sort keys %{$access{$date}{$ip}} ) {
            foreach $net ( sort keys %{$access{$date}{$ip}{$port}} ) {
                print "$date,$ip,$port,$net¥n";
            }
        }
    }
}



先程のログを log.txt という名前で保存して、

2020/05/02,10.10.11.1,telnet,net1
2020/05/02,10.10.12.1,telnet,net2
2020/05/02,10.10.11.1,telnet,net1
2020/05/02,10.10.11.1,ftp,net1
2020/05/02,10.10.12.1,telnet,net2
2020/05/02,10.10.11.1,telnet,net1
2020/05/02,10.10.11.1,telnet,net1

perl hash.plとすると、以下の様になりました。

2020/05/02,10.10.11.1,ftp,net1



2020/05/02,10.10.11.1,telnet,net1
2020/05/02,10.10.12.1,telnet,net2

大丈夫そうですね。
すごく巨大なログをやったりするとどうなるのかわかりませんが。。。


0 件のコメント:

結局 Kindle にケースを買いました。

 こんばんわ 私、最近ほとんど外出しなくなったのですが、妻の買い物に一緒に行って、ぼけーっと待っていたり、病院に行ってぼけーっと待っていたりする機会が多くなり、なんなら家でもボケーっとしていることが非常に多くなったためか、Kindleの出番が結構ありそうです。 前回、タブレットで...