我有一個程序可以將運行的週期數打印到日誌文件中。我想檢索日誌文件中的最後一個值來找出運行週期的總數。我使用下面的代碼:每個正則表達式的最後一場比賽
my @cycles = $log =~ /\s+(\d+)\s+Cycles/gsm;
$run{cycles} = $cycles[-1] if @cycles;
是否有存儲的最後一個匹配的值,這樣我可以使用,而不是在一個陣列收集週期的perl的特殊變量?
我有一個程序可以將運行的週期數打印到日誌文件中。我想檢索日誌文件中的最後一個值來找出運行週期的總數。我使用下面的代碼:每個正則表達式的最後一場比賽
my @cycles = $log =~ /\s+(\d+)\s+Cycles/gsm;
$run{cycles} = $cycles[-1] if @cycles;
是否有存儲的最後一個匹配的值,這樣我可以使用,而不是在一個陣列收集週期的perl的特殊變量?
你可以使用一個負先行斷言:
($run{cycles}) = $log =~ /\s+(\d+)\s+Cycles(?!.*\s+\d+\s+Cycles)/gsm;
意爲「發現的由空格前面和後面的空格 和文字Cycles
數字序列,也就是後面沒有空格的另一序列,數字,空白和文字Cycles
「。
我想這是你想要什麼:
my @cycles = $log =~ /\s+(\d+)\s+Cycles/gsm;
$run{cycles} = $+ if @cycles;
請注意,squiguy表示,$1
應該做的伎倆太(至少它爲我的作品)。
最後,如果你不真的需要所有周期保存到一個數組,但只是想最後一個值,你可以這樣做:
($run{cycles}) = $log =~ /.+\s(\d+)\s+Cycles/s;
你的問題是不完整的。您沒有在您的代碼中顯示您將日誌文件寫入$ 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數量是相同的,但內存使用量要低得多。
你原來的計劃是:
這個程序是:
我不會建議將整個日誌文件讀入內存,但如果沒有關於您在做什麼的更多信息,我不能寫出適當的逐行解決方案。
與/g
修飾符正則表達式停止在下一個比賽,所以你只需要一個while
循環。
注意,存在使用/m
或/s
改性劑是沒有意義的,因爲他們做的是修改的元字符^
,$
和.
的功能。既然你沒有使用這些,他們沒有任何作用。
while ($log =~ /\s+(\d+)\s+Cycles/g) {
$run{cycles} = $1;
}
爲什麼不只是使用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;
}
它應該是一個整體快得多。
你的意思是「$ 1」嗎?看看'perldoc perlvar'。你在正則表達式中捕獲它,你只需要使用它。 – squiguy 2013-03-14 17:22:53
不,$ 1包含匹配的第一個字符串,而不是最後一個。在我的情況下,正則表達式會在文件中找到幾個匹配,我想要最後一次匹配的值 – user2050283 2013-03-14 17:39:33