2013-03-14 93 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; 
} 

應該是一個整體快得多。

相關問題