我正在尝试打开日志文件,针对关键字列表进行搜索,打印包含该关键字的每一行,然后将结果文件压缩为.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);
答案 0 :(得分:3)
你的脚本中可能没有while (<>)
循环,因为这一行涉及键盘的输入。
$logfile
constructor返回的对象IO::Uncompress::Gunzip->new
可以像普通的文件句柄一样处理,因此你可以像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
数组包含来自日志的所有行,其中包含您在第三个($line[2]
)开始时的一个关键字,由&#39; \ t&#39;子。 %keywords
哈希包含关键字作为键及其出现频率作为值。
注意(编辑):您可以以散列形式存储日志,其中每个键可以是关键字和每个值 - 匹配行(或子串或两者)的数组/散列。我只是将匹配的行推入数组中。您可以根据需要进行操作,然后以方便的方式使用gzip打包
另外,最好不要使用像FILE
这样的全局名称,因为在这种情况下,有其他代码偶然使用它的风险。除了验证您是否已成功打开文件句柄,例如例如or die
。
答案 1 :(得分:1)
IO :: Uncompress :: Gunzip-&gt; new返回一个IO :: Uncompress :: Gunzip对象。
foreach my $line ($logfile) {
while (<>) {
...
}
}
毫无意义,它只是将$ line设置为IO :: Uncompress :: Gunzip对象,然后等待键盘输入。
而是尝试:
while (my $line = <$logfile>) {
...
}
您也没有正确使用IO :: Compress :: Gzip。您可以在处理日志文件之前创建IO :: Compress :: Gzip对象,并将其与print一起使用。以下内容应该有效:
...
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;
}
您应该查看IO :: Uncompress :: Gunzip和IO :: Compress :: Gzip的文档(使用perldoc或cpan.org)。它显示了正确使用这些模块的示例。