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
} |
发现当作业数为数千时,此脚本将花费很长时间来输出信息。
有什么办法可以提高效率?
谢谢!
-
您能否发布host.log的简短示例?
-
@Tuga,您好,抱歉,由于该日志与我公司的产品有关,因此我可能无法提供该日志。 它可能与日志的内容有关吗? 每个日志将有几千行,并且"信息"是随机分布的。
-
您可以将.*替换为(?>[^(\
]++|\\((?!\\d+\\)))*
-
什么是"很长时间"? 您是否测试过以查看是否是您的grep花费了时间或之后的东西? (仅带>devnull的grep命令需要多长时间?)
虽然使用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;
} |