2014-03-13 46 views
0

我有一個文本文件,它看起來像這樣:如何在我的文本文件中找到以「PASS」結尾的最後一行?

--------- Voltage = 1.150000 V --------->PASS 




--------- Voltage = 1.140000 V --------->PASS 




--------- Voltage = 1.130000 V --------->PASS 




--------- Voltage = 1.120000 V --------->PASS 




--------- Voltage = 1.110000 V --------->PASS 




--------- Voltage = 1.100000 V --------->PASS 




--------- Voltage = 1.090000 V --------->FAIL 

我想找回過去的傳球值,在這種情況下是1.100000V。我如何用正則表達式來做到這一點?我嘗試以下,但它並沒有給出正確的答案:

open(my $FH, $FileName) or die "$!\n"; 

while($line = <$FH>) 
{ 
    if($line =~ /FAIL/) 
    { 
     if($line =~ m/^\d*\.?\d*/) #check for the decimal number? not sure 
     { 
      print $&; # I intend to print the matched number here? 
     } 
    } 
} 
+0

我使用的定界符是「\ n \ n \ n \ n」。 定義爲$/=「\ n \ n \ n \ n」; – user3368737

+0

謝謝大家的幫助,我會跟進這個問題。 使用我的最終解決方案或其他問題向您提供更新。 Perl有這樣一個活躍的社區。 – user3368737

回答

1

您正在尋找一些在因爲^的字符串的開始。當然,那裏沒有一個。你可以用/(\d+(?:\.\d+))/提取數字,但爲什麼不採取以下Voltage =

你說你想要最後通過的電壓,但你試圖捕捉失敗的電壓!

避免$&,因爲它會減慢每次比賽和替換而不捕獲。

open(my $FH, $FileName) 
    or die "$!\n"; 

my $passing_voltage; 
while ($line = <$FH>) { 
    if (my ($voltage) = $line =~ /Voltage = (\S+)/) { 
     last if $line =~ /FAIL/; 
     $passing_voltage = $voltage; 
    } 
} 

die("No passing voltage\n") if !defined($passing_voltage); 
print("$passing_voltage\n"); 

無需觸摸$/


以上內容非常簡單,但可以通過從頭到尾閱讀文件進一步簡化。

use File::ReadBackwards qw(); 

my $fh = File::ReadBackwards->new($FileName) 
    or die("$!\n"); 

my $voltage; 
while (defined(my $line = $fh->readline())) { 
    if ($line =~ /Voltage = (\S+).*PASS/) { 
     $voltage = $1; 
     last; 
    } 
} 

die("No passing voltage\n") if !defined($voltage); 
print("$voltage\n"); 
+0

謝謝你的幫助。 – user3368737

+0

這會捕獲失敗的值,但最後一個良好傳球值在哪裏? – alexmac

+1

是的,你是對的。關於最後一個良好的傳球價值。 當所有通過,最後通過應該是期望值。 當它在任何時候失敗,那麼最後的良好傳球價值是預期值。 這個問題仍然是公開的。 – user3368737

1

這將讀取整個文件,然後打印匹配的最後一行的編號。

while (<>) 
{ 
    # last if m/FAIL$/; # see below 
    next unless m/(\d+\.\d) V/; # Capture number in $1 
    $keep = $1 if m/PASS$/; 
} 
print $keep; 

爲了優化,如果你知道第一個FAIL不會跟任何PASS ES,取消對last線。

作爲一襯墊,

perl -ne 'next unless m/(\d+\.\d+) V .*PASS$/; $k = $1; END { print $k }' filename 
+0

輸入文件不是鍵盤。 – alexmac

+0

@alexmac在調用腳本時,文件名需要作爲命令行參數傳遞。 – ThisSuitIsBlackNot

+1

+1我個人喜歡你的單行!雖然它(和你的更完整的答案)會失敗,如果有人在背對背的前面進行了探測,並且電壓消失:-) –

-2

Hmmmm。

open(my $FH, $FileName) or die "$!\n"; 
# suggested change for poster is 
# open (FH, $fileName) } or die "found not open file $1\n"; 
$lastPass = "init"; # in the event of a fail on first line. 

while($line = <FH>){ 
    next if $line =~ /^$/; # if no string data why even bother 
    if($line =~ /FAIL/i){ # look for a fail 
     print "fail detected $line \n"; #print a warning 
     last;  # exit the loop 
    } 
    else { 
    if ($line =~ m/(\d*\.?\d*)/) { # if the line is not a fail record 
     $lastPass = $line; 
     $voltage = $1; # voltage if you want it in the $1 regex memory 
    }  
    } 

} 
# close (FH); # suggestion 
if ($lastPass eq "init") { # did we find a fail before a pass. 
    print "detected fail before good data \n"; 
} 
else { 
    print $lastPass, "\n"; 
    print $voltage , "\n"; 
} 
+0

太棒了,那很優雅。 一個小問題,如果你定義了$ pass但是永遠不修改它們之間的值,那麼if($ pass eq「init」)將會被打印出來。 – user3368737

+0

它的功能,當然,但不優雅。有可以刪除,以使它[優雅]的cruft(http://stackoverflow.com/a/22384342/589924) – ikegami

+1

不用'use strict;'編譯。 – ThisSuitIsBlackNot

相關問題