我想使用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
}
发现当作业号为几千时,此脚本将需要很长时间才能输出信息。
有没有办法提高效率?
谢谢!
答案 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
}