2013-03-14 88 views
0

我有一个程序可以将运行的周期数打印到日志文件中。我想检索日志文件中的最后一个值来找出运行周期的总数。我使用下面的代码:每个正则表达式的最后一场比赛

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

是否有存储的最后一个匹配的值,这样我可以使用,而不是在一个阵列收集周期的perl的特殊变量?

+4

你的意思是“$ 1”吗?看看'perldoc perlvar'。你在正则表达式中捕获它,你只需要使用它。 – squiguy 2013-03-14 17:22:53

+0

不,$ 1包含匹配的第一个字符串,而不是最后一个。在我的情况下,正则表达式会在文件中找到几个匹配,我想要最后一次匹配的值 – user2050283 2013-03-14 17:39:33

回答

1

你可以使用一个负先行断言:

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

意为“发现的由空格前面和后面的空格 和文字Cycles数字序列,也就是后面没有空格的另一序列,数字,空白和文字Cycles“。

1

我想这是你想要什么:

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

请注意,squiguy表示,$1应该做的伎俩太(至少它为我的作品)。

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

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

你的问题是不完整的。您没有在您的代码中显示您将日志文件写入$ log的部分内容。假设你的日志文件的名称是$日志文件你的问题是如何提高:

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中最长行的空间而不是整个文件的空间,以及用于存储单个周期而不是全部空间的空间。

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

你原来的计划是:

  1. 打开日志文件,啜整个日志文件的内容,关闭lofile
  2. 找到所有的周期记录
  3. 使用的最后一个周期记录,如果有的话

这个程序是:

  1. 打开日志文件
  2. 读取日志文件的一行一时间
    • 记得看到
  3. 最后一个周期关闭最后一个周期看到该日志文件
  4. 使用,如果有的话
1

我不会建议将整个日志文件读入内存,但如果没有关于您在做什么的更多信息,我不能写出适当的逐行解决方案。

/g修饰符正则表达式停止在下一个比赛,所以你只需要一个while循环。

注意,存在使用/m/s改性剂是没有意义的,因为他们做的是修改的元字符^$.的功能。既然你没有使用这些,他们没有任何作用。

while ($log =~ /\s+(\d+)\s+Cycles/g) { 
    $run{cycles} = $1; 
} 
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; 
} 

应该是一个整体快得多。

相关问题