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

Dra*_*rys 1 regex perl grep

我想使用perl从位于以下目录结构中的日志文件中获取一些日志信息: $jobDir/jobXXXX/host.logwhere 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      
    }
Run Code Online (Sandbox Code Playgroud)

发现当作业号为几千时,该脚本将花费很长时间来输出信息.

有没有办法提高效率?

谢谢!

Lee*_*hem 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;
}
Run Code Online (Sandbox Code Playgroud)


Ste*_*ich 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      
}
Run Code Online (Sandbox Code Playgroud)