2008-12-03 98 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"; 
相关问题