2008-12-03 99 views
4

的Perl似乎殺了我的陣列,每當我讀文件:爲什麼調用這個函數會改變我的數組?

my @files = ("foo", "bar", "baz"); 
print "Files: " . join(" ", @files) . "\n"; 

foreach(@files) { 
    print "The file is $_\n"; 
    func(); 
} 

sub func { 
    open(READ, "< test.txt"); 
    while(<READ>) { 
    } 
    close READ; 
} 

print "Files: " . join(" ", @files) . "\n"; 

生產:

Files: foo bar baz 
The file is foo 
The file is bar 
The file is baz 
Files: 

但是當我註釋掉func(),它給了我會一直期待:

Files: foo bar baz 
The file is foo 
The file is bar 
The file is baz 
Files: foo bar baz 

任何想法,爲什麼會發生這種情況?

回答

12

您必須更改foo以本地化$_或在您的循環中不使用$_。最好的是,一舉兩得:

foreach my $filename (@files) { 
    print "The file is $filename\n"; 
    func(); 
} 

sub func { 
    local $_; 
    open my $read, '<', 'test.txt' or die "Couldn't open test.txt: $!"; 
    while(<$read>) { 
    } 
    close $read or die "Couldn't close file: $!"; 
} 

foreach循環別名$_到文件的當前名稱和while(<READ>)分配給$_。這是一個不錯的魔法組合,可以這麼說。

一般來說,依靠$_以外的其他任何東西都不是一個好主意。

+0

my $ _; (僅限5.10+)是更好的方法 – ysth 2008-12-03 04:37:00

+0

確實如此,但分佈僅開始移至5.10。我認爲大部分人仍然在5.8。 – 2008-12-03 13:47:20

3

這應該是Leon的回答,但我還沒有名聲;我很抱歉。

小錯誤:$ filename也應該在foreach循環的主體中替換$ _。

Minor nitpick:我建議始終使用open的三個參數形式使用詞法文件句柄,即使在很短的示例中。

foreach my $filename (@files) { 
    print "The file is $filename\n"; 
    func(); 
} 

sub func { 
    open my $read, '<', 'test.txt' or die $!; 
    while(<$read>) { 
    } 
    close $read or die $!; 
} 

print 'Files: ' . join(' ', @files) . "\n"; 
相關問題