2010-08-25 346 views
2

我是Perl新手,在逐行讀取文件時遇到問題。我從一個建議使用while循環的教程開始。這工作得很好,但是我想要有一個選項可以在出現錯誤時跳出循環。我知道我可以使用「last」關鍵字,但我不太喜歡這一點,我想將它包含在while循環的布爾表達式中,以便更容易地瞭解它停止的條件。所以我做了Perl while循環/讀取文件

$error=0; 
while ((!$error) && (<MYFILE>)) { 
print $_; 
...  
} 

不幸的是,這不起作用,因爲$ _似乎包含「未初始化的值」。出於某種原因,當我將(!$ error)更改爲(!0)時,它會再次運行。我會理解,如果我使用了||,那麼它不起作用由於懶惰的評估,但在這種情況下,需要評估兩邊,所以我不明白爲什麼它不初始化行變量。

+6

瞭解您正在學習的語言的習語(任何語言) - 而「last」是Perl的成語之一。 – 2010-08-25 14:33:03

+1

正如我在問題中所說的,我知道最後一個關鍵字。 – bufferUnderrun 2010-08-25 14:48:28

+1

好,那麼,學會*擁抱*語言的成語。 – 2010-08-25 21:22:56

回答

5

神奇分配$_只有當沒有別的在循環出現:

​​

如果你想在錯誤的測試太 - 不推薦 - 那麼你需要做的任務:

my $error = 0; 
while (!$error && ($_ = <MYFILE>)) { 
    print; 
    $error = 1 if m/quit/i; 
} 

不要忘了補充:

use warnings; 
use strict; 

之所以版本'!0'sion的工作原理可能是因爲Perl優化並認識到'!0'始終爲真,並將其從循環中移除,只留下I/O操作符,然後將其分配給$_

NB:它是迄今爲止最好使用慣用的Perl和last聲明:

while (<MYFILE>) { 
    print; 
    last if m/quit/i; 
} 
+0

我相信你需要在while循環條件中在$ _上添加一個「defined」檢查,否則包含「0」的文件中的一行將被評估爲false並結束循環。所以,像這樣:while(!$ error && defined($ _ = )){... – 2010-08-25 14:46:53

+0

好的,謝謝,我不知道循環的本質。如果循環的所有條件都在一個地方,我認爲它會提高可讀性。在大學時,我被教GOTO和 - 在較小的範圍內 - 破壞性陳述是邪惡的,所以我一直試圖避免它們。但我會使用你建議的版本。 – bufferUnderrun 2010-08-25 14:54:33

+0

@Matthew:不,你不需要那樣做。該行還包含一個換行符(在需要時可通過'chomp'去除)。我想如果一個文件以換行符後跟0(並且沒有尾隨換行符)結尾,那麼你可能是正確的 - 但這不是標準的文本文件。 – 2010-08-25 16:23:10

3

首先,喬納森指出你應該總是寫語言地道,除非你有一個很好的理由,在這裏你不」噸。

您的大問題是誤解了while循環。只有在while條件測試中只有它是角度運算符的結果自動分配給$_纔會發生。如果條件測試中有多個項目,則會對它們進行評估並丟棄(Programming Perl第80-81頁和I/O Operators at Perldoc)。