2013-02-15 58 views
0

後續代碼會吃@populations的perl的foreach吃所有的數組內容

@populations=("EUR","AFR","ASN","AMR"); 
print @populations,"\n"; #will show EURAFRASNAMR 
foreach (@populations) 
{ 
    $filepath="tmp.txt"; #whatever text file you like 
    open(FILE,"<$filepath"); 
    while(<FILE>) 
    { 
    } 
} 
print @populations,"\n"; #will print nothing 

的內容,如果改變

foreach $i (@populations) 

則數組將不會被吃掉。如果標記while循環,則數組不會被吃掉。

我不是perl大師,但有幾年的經驗。

誰能告訴我爲什麼?它是一個Perl的錯誤?

回答

5
while (<$fh>) { ... } 

獲取與

while (defined($_ = <$fh>)) { ... } 

這就是爲什麼讀取的值是$_可更換。值得注意的是,$_目前已被別名爲@populations的元素。

正如你所說,你可以通過使用

for my $population (@populations) { 
    ... 
    while (<FILE>) { ... $_ ... } 
    ... 
} 

避免這樣的問題,但仍然可以從調用子揍$_。這裏有兩個更強大的修復:

for (@populations) { # Or: for my $population (@populations) { 
    ... 
    while (my $line = <FILE>) { ... $line ... } 
    ... 
} 

for (@populations) { # Or: for my $population (@populations) { 
    ... 
    while (local $_ = <FILE>) { ... $_ ... } 
    ... 
} 

完全相同的原因,你不應該使用全局變量文件句柄。

$filepath="tmp.txt"; #whatever text file you like 
open(FILE,"<$filepath"); 
<FILE> 

應該

my $filepath="tmp.txt"; 
open(my $FILE, "<", $filepath) or die $!; 
<$fh> 

順便說一句,總是用use strict; use warnings;

6

不是一個確切的錯誤,但它是一個不知情的陷阱。您隱式地將@populations的元素分配給$_變量,然後您正在將數據從FILE文件句柄讀取到$_中,覆蓋@populations的內容。

@populations=("EUR","AFR","ASN","AMR"); 
print @populations,"\n"; #will show EURAFRASNAMR 
foreach $_ (@populations) # $_ becomes "aliased" to the element in @populations 
{ 
    $filepath="tmp.txt"; #whatever text file you like 
    open(FILE,"<$filepath"); 
    while(defined($_ = <FILE>)) # overwrites $_, and erases element in @populations 
    { 
    } 
} 
print @populations,"\n"; #will print nothing 

你找到了一個很好的解決辦法,這是爲了避免在for循環使用$_含蓄:

更明確地說,你的代碼是等價的。

+0

謝謝你們! – user1143669 2013-02-15 22:10:22

相關問題