Perl正则表达式最后一场比赛

时间:2013-03-14 17:17:13

标签: regex perl

我有一个程序可以将它运行的周期数打印到日志文件中。我想检索日志文件中的最后一个值,以找出运行的循环总数。我正在使用以下代码:

my @cycles = $log =~ /\s+(\d+)\s+Cycles/gsm;
$run{cycles} = $cycles[-1] if @cycles;

是否有一个perl特殊变量存储最后匹配的值,以便我可以使用它而不是收集数组中的循环?

5 个答案:

答案 0 :(得分:1)

您可以使用负面预测断言:

($run{cycles}) = $log =~ /\s+(\d+)\s+Cycles(?!.*\s+\d+\s+Cycles)/gsm;

意思是“找到以空格开头的数字序列,后跟空格 和文字Cycles,后面跟着另一个空格,数字,空格和文字Cycles“序列。

答案 1 :(得分:1)

我认为这就是你想要的:

my @cycles = $log =~ /\s+(\d+)\s+Cycles/gsm;
$run{cycles} = $+ if @cycles;

请注意,正如暧昧所说,$1也应该做到这一点(至少它对我有用)。

最后,如果你真的不需要保存数组中的所有循环,但只想要最后一个值,你可以这样做:

($run{cycles}) = $log =~ /.+\s(\d+)\s+Cycles/s;

答案 2 :(得分:1)

我不建议将整个日志文件读入内存,但如果没有关于您正在做什么的更多信息,我就无法编写正确的逐行解决方案。

带有/g修饰符的正则表达式模式在 next 匹配时停止,因此您只需要while循环。

请注意,使用/m/s修饰符毫无意义,因为他们只需修改元字符^$和{{}的功能1}}。由于你没有使用这些,它们没有任何效果。

.

答案 3 :(得分:0)

您的问题不完整。您没有显示代码中将日志文件粘贴到$ log中的部分。假设您的日志文件的名称在$ logFile中,那么您的问题是如何改进:

my $log = do { local( @ARGV, $/ ) = $logFile ; <> } ;
my @cycles = $log =~ /\s+(\d+)\s+Cycles/gsm;
$run{cycles} = $cycles[-1] if @cycles;

答案是一次读取一行日志文件:

open my $logFH,'<',$logFile
  or die "Could not open $logFile: $!";

my $cycles;
while (my $logLine = <$logFH>) {
    ($cycles) = $logLine =~ /\s+(\d+)\s+Cycles/;
}
close $logFH;

$run{cycles} = $cycles
  if $cycles;

这样你的程序只使用$ logFile中最长行的空格而不是整个文件的空间,以及存储单个Cycle而不是所有文件的空间。

也就是说,I / O的数量相同,但内存使用率要低得多。

您原来的节目是:

  1. 打开日志文件,Slurp整个日志文件的内容,关闭lofile
  2. 查找记录的所有周期
  3. 使用记录的最后一个周期(如果有)
  4. 该计划是:

    1. 打开日志文件
    2. 一次读取一行日志文件
      • 记住上次见过的周期
    3. 关闭日志文件
    4. 使用上次看到的循环,如果有的话

答案 4 :(得分:0)

为什么不使用File::ReadBackwards并采用“第一”匹配线。

$bw = File::ReadBackwards->new( 'log_file' ) 
    or die "can't read 'log_file' $!" 
    ;
while( defined( $log_line = $bw->readline ) ) {
    next unless m/\s+(\d+)\s+Cycles/;
    print;
    last;
}

应该快一点。