而在 foreach 内部会杀死原始数组
while inside foreach kills original array
出于某种原因,我的原始数组被这段代码清除了。我不明白为什么? @my_array 在 运行 之后为空,我取出了 while 循环中的所有工作以查看是否是原因,但不是。
foreach (@my_array)
{
open MY_FH, "<", $_;
while (<MY_FH>)
{
}
close MY_FH;
}
它不是空的,它只是充满了undef
。
while (<MY_FH>)
是 while (defined($_ = <MY_FH>))
的语法糖。由于 foreach
循环中的变量是原始值的别名,因此 $_
中的文件名会被文件的每一行覆盖。 while
循环一直持续到 <MY_FH>
returns undef
指示 EOF。 undef
是存储在 $_
中的最后一个值。
解决方案是在至少一个循环中使用不同的变量。更改 foreach
循环可能会减少工作量:
foreach my $fn (@my_array)
{
open MY_FH, "<", $fn;
while (<MY_FH>)
{
}
close MY_FH;
}
如果在 scalar @my_array
循环后检查 @my_array
的大小,您会发现它没有改变。但是当您访问单个元素时,undef
的数组看起来就像一个空数组,这可能就是您认为它为空的原因。
正如 cjm 所解释的,数组的元素被 while
循环覆盖,因为它从文件读取到 $_
,foreach
为每个数组元素起别名反过来
最简单的解决方案是在 while
循环期间 localise $_
。这会创建 $_
的临时副本,可以在不影响 @my_array
的情况下使用。像这样
for ( @my_array ) {
open my $fh, '<', $_;
local $_; # To protect @my_array
while ( <$fh> ) {
...
}
close $fh;
}
出于某种原因,我的原始数组被这段代码清除了。我不明白为什么? @my_array 在 运行 之后为空,我取出了 while 循环中的所有工作以查看是否是原因,但不是。
foreach (@my_array)
{
open MY_FH, "<", $_;
while (<MY_FH>)
{
}
close MY_FH;
}
它不是空的,它只是充满了undef
。
while (<MY_FH>)
是 while (defined($_ = <MY_FH>))
的语法糖。由于 foreach
循环中的变量是原始值的别名,因此 $_
中的文件名会被文件的每一行覆盖。 while
循环一直持续到 <MY_FH>
returns undef
指示 EOF。 undef
是存储在 $_
中的最后一个值。
解决方案是在至少一个循环中使用不同的变量。更改 foreach
循环可能会减少工作量:
foreach my $fn (@my_array)
{
open MY_FH, "<", $fn;
while (<MY_FH>)
{
}
close MY_FH;
}
如果在 scalar @my_array
循环后检查 @my_array
的大小,您会发现它没有改变。但是当您访问单个元素时,undef
的数组看起来就像一个空数组,这可能就是您认为它为空的原因。
正如 cjm 所解释的,数组的元素被 while
循环覆盖,因为它从文件读取到 $_
,foreach
为每个数组元素起别名反过来
最简单的解决方案是在 while
循环期间 localise $_
。这会创建 $_
的临时副本,可以在不影响 @my_array
的情况下使用。像这样
for ( @my_array ) {
open my $fh, '<', $_;
local $_; # To protect @my_array
while ( <$fh> ) {
...
}
close $fh;
}