当文件数量巨大时,如何提高perl中的grep效率

时间:2014-05-04 14:15:12

标签: regex perl grep

我想使用perl从位于以下目录结构中的日志文件中获取一些日志信息: $jobDir/jobXXXX/host.log其中XXXX是一个工作号码,从1到几千。 $jobDir下没有其他类型的子目录,除jobXXXX下的日志外没有其他文件。脚本是:

my  @Info;  #store the log informaiton
my $Num = 0;
@Info = qx(grep "information" -r $jobDir); #is this OK ?

foreach(@Info){
        if($_=~ /\((\d+)\)(.*)\((\d+)\)/){
            Output(xxxxxxxx);   
        }
        $Num=$Num+1; #number count      
    }

发现当作业号为几千时,此脚本将需要很长时间才能输出信息。

有没有办法提高效率?

谢谢!

2 个答案:

答案 0 :(得分:5)

您应该逐个搜索这些日志文件,并逐行扫描每个日志文件,而不是将grep的输出读取到内存(这可能会耗费大量内存,并且会降低程序速度,甚至是系统):

# untested script

my $Num;
foreach my $log (<$jobDir/job*/host.log>) {
    open my $logfh, '<', "$log" or die "Cannot open $log: $!";
    while (<$logfh>) {
        if (m/information/) {
            if(m/\((\d+)\)(.*)\((\d+)\)/) {
                Output(xxx);
            }
            $Num++;
        }
    }
    close $logfh;
}

答案 1 :(得分:5)

虽然使用perl内置的匹配会更优雅(参见另一个答案),但调用grep命令可以更高效,更快,特别是如果有大量数据但只有少数匹配。但是你调用它的方法是首先运行grep并收集所有数据,然后扫描所有数据。这将需要更多内存,因为您首先收集所有数据,并且必须等待输出直到收集所有数据。收集第一批数据后,最好立即输出:

open( my $fh,'-|','grep',"information",'-r',$jobDir) or die $!;
while (<$fh>) {
    if(/\((\d+)\)(.*)\((\d+)\)/){
        Output(xxxxxxxx);
    }
    $Num=$Num+1; #number count      
}