2016-05-11 4 views
0

ログファイルを開き、キーワードのリストに対して検索し、そのキーワードを含むすべての行を出力し、結果ファイルを.gzに圧縮しようとしています。圧縮されたログファイルをキーワードリストと照合して検索する

コンパイルエラーなしで実行を開始する以下のコードを用意しました。結果ファイルに書き込みますが、スクリプトを実行すると完了することはなく、決して結果が見つかりません。どんな助け?この行は、キーボードからの入力を伴うため

#!/usr/bin/perl 

use IO::Uncompress::Gunzip qw($GunzipError); 
use IO::Compress::Gzip qw(gzip $GzipError) ; 
use diagnostics; 
use strict; 
use warnings; 

my %LOGLINES =(); 
my %count =(); 

open(FILE, "</data/bro/scripts/Keywords.txt"); 
my %keywords = map { chomp $_; $_, 1 } <FILE>; 
close(FILE); 

my $logfile = IO::Uncompress::Gunzip->new("/data/bro/logs/2016-05-05/http.00:00:00-06:00:00.log.gz") 
    or die "IO::Uncompress::Gunzip failed: $GunzipError\n"; 

open(FILE, "+>Results.txt"); 
my @results = <FILE>; 

foreach my $line ($logfile) { 
    while (<>) { 
     my @F=split("\t"); 
      next unless ($F[2] =~ /^(199|168|151|162|166|150)/); 

     $count{ $F[2] }++; 

     if ($count{ $F[2] } == 10) { 
      print @{ $LOGLINES{$F[2]} }; # print all the log lines we've seen so far 
      print $_;      # print the current line 
     } elsif ($count{ $F[2] } > 10) { 
      print $_;      # print the current line 
     } else { 
      push @{ $LOGLINES{$F[2]} }, $_; # store the log line for later use 
     } 

    my $flag_found = grep {exists $keywords{$_} } split /\s+/, $line; 
    print $line if $flag_found; 
    } 
} 
IO::Compress::Gzip("results.gz") 
      or die "IO::Compress::Gunzip failed: $GzipError\n"; 
close(FILE); 
+2

一般に、while(<>)行にはキーボード入力が含まれます。おそらく、これがあなたのスクリプトが「完了しない」理由です。 – red0ct

+0

@ red0ctは正しいです。 'while'ループの意図は何ですか?あなたはものを入力してほしい。あなたはすでに '$ logfile'の行を' foreach'でループしています(これは:: Gunzipオブジェクトで何も呼び出さないためです)。 – simbabque

+0

whileループは、最後に達するまでログファイルの各行を検索し続けることでした。私はそれについて間違ったやり方をしましたか? –

答えて

3

はおそらく、あなたのスクリプトでwhile (<>)ループで必要はありません。

オブジェクトIO::Uncompress::Gunzip->newconstructorによって返さ$logfileは、あなただけ行うことができますので、通常のファイルハンドルと同様に扱うことができるようにwhile (<$logfile>)

use IO::Uncompress::Gunzip qw($GunzipError); 
use IO::Compress::Gzip qw(gzip $GzipError) ; 
use strict; 
use warnings; 
use feature 'say'; 

#... 
my @loglines; 

open my $fh, '</data/bro/scripts/Keywords.txt' or die "$!"; 
my %keywords = map { chomp; $_ => 0 } <$fh>; 
close $fh; 

my $logfile = IO::Uncompress::Gunzip->new("...") 
    or die "IO::Uncompress::Gunzip failed: $GunzipError\n"; 

while (<$logfile>) { 
    my @line = split /\t/; 
    next if ! $line[2]; 
    for my $key (keys %keywords) { 
     if ($line[2] =~ /^$key/) { $keywords{$key}++; push @loglines, $_; say; last } 
    } 
} 
# ... pack using gzip 

だから@loglines配列はであなたのキーワードのいずれかを含むログからのすべての行が含まれています'\ t'部分文字列で分割された3番目($line[2])の先頭になります。 %keywordsハッシュには、キーとしてのキーワードとその発生頻度が値として含まれています。


NOTES(編集):あなたがハッシュでloglinesを格納することができ、各キーは、キーワードと各値とすることができる - アレイ/マッチラインのハッシュ(またはサブストリングまたは両方)。私は単純に例えばマッチした行を配列にプッシュします。必要に応じてそれを実行し、gzipを便利な方法でパックすることができます。
FILEのようなグローバル名を使用しない方が良いでしょう。そのような場合、偶然に他のコードを使用する危険性があるからです。あなたがファイルハンドルを正常に開いたことを確認するだけでなく、例のようにor dieとなります。

+0

@MichaelMeisが編集されました。 [this](http://stackoverflow.com/questions/3276674/which-one-is-good-practice-a-lexical-filehandle-or-a-typeglob) – red0ct

1

IO :: Uncompress :: Gunzip-> newは、IO :: Uncompress :: Gunzipオブジェクトを返します。

foreach my $line ($logfile) { 
    while (<>) { 
     ... 
    } 
} 

は意味をなさないので、$ lineをIO :: Uncompress :: Gunzipオブジェクトに設定し、キーボード入力を待ちます。

代わりにしてみてください:

while (my $line = <$logfile>) { 
    ... 
} 

ます。また、IO ::圧縮を使用していない:: Gzipでは正しく。ログファイルを処理してプリントで使用する前に、IO :: Compress :: Gzipオブジェクトを作成することができます。次のようなものは動作するはずです:

... 
my $z = IO::Compress::Gzip->new("results.gz") 
      or die "IO::Compress::Gunzip failed: $GzipError\n"; 
while (my $line = <$logfile>) { 
    my @F=split("\t", $line); 
     next unless ($F[2] =~ /^(199|168|151|162|166|150)/); 

    $count{ $F[2] }++; 

    if ($count{ $F[2] } == 10) { 
     print $z @{ $LOGLINES{$F[2]} }; # print all the log lines we've seen so far 
     print $z $line;      # print the current line 
    } elsif ($count{ $F[2] } > 10) { 
     print $z $line;      # print the current line 
    } else { 
     push @{ $LOGLINES{$F[2]} }, $_; # store the log line for later use 
    } 

    my $flag_found = grep {exists $keywords{$_} } split /\s+/, $line; 
    print $z $line if $flag_found; 
} 

あなたは:: Gzipで圧縮(はperldocを使用したりcpan.orgで):: IO ::解凍:: GunzipのとIOのドキュメントをご覧ください。これらのモジュールの正しい使い方の例を示しています。

+0

ありがとう、私はまだです王座的に混乱しましたが、私はこれが正しい方向に向かっていると思います。私はもっ​​とgzipを読んで、新しいエラーを研究しています。 –

関連する問題