关于regex:文件数量巨大时如何提高Perl中的grep效率

how to improve grep efficiency in perl when the file number is huge

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

1
2
3
4
5
6
7
8
9
10
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      
    }

发现当作业数为数千时,此脚本将花费很长时间来输出信息。

有什么办法可以提高效率?

谢谢!


虽然使用perl内置的匹配会更好(请参见其他答案),但调用grep命令会更高效,更快捷,尤其是在有大量数据但匹配很少的情况下。 但是,调用它的方式是先运行grep并收集所有数据,然后扫描所有数据。 这将需要更多的内存,因为您首先要收集所有数据,并且必须等待输出,直到收集了所有数据。 最好是在收集第一个数据后立即输出:

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

您应该一个个地搜索这些日志文件,并逐行扫描每个日志文件,而不是将grep的输出读取到内存中(这可能会占用大量内存,并降低程序速度,甚至导致系统运行缓慢):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 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;
}