5

2013 年 5 月 10 日更新

よし、問題なく IP アドレスを除外できるようになりました。次の 3 つのやりたいことは、 で簡単に実行できると思っていましたsort($keys)が、間違っていたので、以下のもう少し複雑なアプローチを試しても解決策にはなりませんでした。次に達成する必要があるのは、日付とブラウザーのバージョンを収集することです。ログ ファイルのフォーマットと現在のコードのサンプルを提供します。

アパッチログ

24.235.131.196 - - [10/Mar/2004:00:57:48 -0500] "GET http://www.google.com/iframe.php HTTP/1.0" 500 414 "http://www.google.com/iframe.php" "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98)"

マイコード

#!usr/bin/perl -w
use strict;

my %seen = ();
open(FILE, "< access_log") or die "unable to open file  $!";    

while( my $line = <FILE>) {
    chomp $line;

    # regex for ip address.
    if( $line =~ /(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})/ ) {  
        $seen{$1}++;
    }

    #regex for date an example is [09\Mar\2009:05:30:23]
    if( $line =~ /\[[\d]{2}\\.*[\d]{4}\:[\d]{2}\:[\d]{2}\]*/) {
        print "\n\n $line matched : $_\n";
    }

}
close FILE;
my $i = 0;

# program bugs out if I uncomment the below line, 
# but to my understanding this is essentially what I'm trying to do.
# for my $key ( keys %seen ) (keys %date) {
for my $key ( keys %seen ) {
    my ($ip) = sort {$a cmp $b}($key); 
    # also I'd like to be able to sort the IP addresses and if 
    # I do it the proper numeric way it generates errors saying contents are not numeric. 
    print @$ip->[$i] . "\n";
    # print "The IPv4 address is : $key and has accessed the server $seen{$key} times. \n";
    $i++;
}
4

1 に答える 1

5

あなたはかなり近いです。はい、私はhash. これは一般に「見られたハッシュ」と呼ばれます。

#!usr/bin/perl 

use warnings;
use strict;

my $log = "web.log";
my %seen = ();

open (my $fh, "<", $log) or die "unable to open $log: $!"; 

while( my $line = <$fh> ) {
    chomp $line;

    if( $line =~ /(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})/ ){
        $seen{$1}++;
    }
}
close $fh;

for my $key ( keys %seen ) {
    print "$key: $seen{$key}\n";
}

いくつかの出力を含むサンプル ログ ファイルを次に示します。

$ cat web.log 
[Mon Sep 21 02:35:24 1999] some msg blah blah
[Mon Sep 21 02:35:24 1999] 192.1.1.1
[Mon Sep 21 02:35:24 1999] 1.1.1.1
[Mon Sep 21 02:35:24 1999] 10.1.1.9
[Mon Sep 21 02:35:24 1999] 192.1.1.1
[Mon Sep 21 02:35:24 1999] 10.1.1.5
[Mon Sep 21 02:35:24 1999] 10.1.1.9
[Mon Sep 21 02:35:24 1999] 192.1.1.1
$ test.pl
1.1.1.1: 1
192.1.1.1: 3
10.1.1.9: 2
10.1.1.5: 1

私が注意するいくつかのこと:

my @array = <FH>;これにより、ファイル全体がメモリに読み込まれますが、これは良い考えではありません。特にこの場合、ログ ファイルはかなり大きくなる可能性があります。rotated適切でない場合はなおさらです。forまたはforeach、これと同じ問題が発生します。whileファイルから読み取るためのベストプラクティスです。

open上記の例のように、レキシカル スコープの 3-arg を使用する習慣があるはずです。

あなたのdie声明はそれほど「正確」であってはなりません。についての私のメッセージを参照してくださいdie。理由は権限である可能性があるため、存在しない、ロックされているなど...

アップデート

これはあなたの日付で機能します。

my $line = '[09\Mar\2009:05:30:23]: plus some message';

#example is [09\Mar\2009:05:30:23]
if( $line =~ /(\[[\d]{2}\\.*\\[\d]{4}:[\d]{2}:[\d]{2}:[\d]{2}\])/ ){
   print "$line matched: $1\n"; 
}

更新2

あなたが間違ったことをしたことがいくつかあります。

あなたが何かを date に保存しているとは思いませんhash

print "\n\n $line matched : $_\n";

あなたの のように見えるはずですが、seen hashあまり意味がありません。この保存された日付データで何をしようとしていますか?

$data{$1} = "some value, which is up to you";

hashes1 つのループで 2 つをループすることはできませんfor

for my $foo (keys %h)(keys %h2) { # do stuff }

そして、最後の並べ替えビットについてはsortkeys

for my $key (sort keys %seen ) {
于 2013-05-10T05:41:57.337 に答える