Perl foreach循环变量作用域

Perl foreach循环变量作用域,perl,foreach,scope,Perl,Foreach,Scope,我是perl新手,在编写以下代码片段后,我对perl范围规则感到困惑: #!/usr/bin/perl my $i = 0; foreach $i(5..10){ print $i."\n"; } print "Outside loop i = $i\n"; 我期望输出如下: 5 6 7 8 9 10 Outside loop i = 10 但它的给予: 5 6 7 8 9 10 Outside loop i = 0 因此,变量$i的值在循环退出后不会改变。这是怎么回事 forea

我是perl新手,在编写以下代码片段后,我对perl范围规则感到困惑:

#!/usr/bin/perl
my $i = 0;
foreach $i(5..10){
    print $i."\n";
}
print "Outside loop i = $i\n";
我期望输出如下:

5
6
7
8
9
10
Outside loop i = 10
但它的给予:

5
6
7
8
9
10
Outside loop i = 0

因此,变量$i的值在循环退出后不会改变。这是怎么回事

foreach
将变量本地化为循环

use strict;
use warnings;

my $adr;
my $i = 0;
foreach $i(5..10){
    $adr = \$i;
    print "$i ($adr)\n";
}
$adr = \$i;
print "Outside loop i = $i ($adr)\n";
输出

5 (SCALAR(0x9d1e1d8))
6 (SCALAR(0x9d1e1d8))
7 (SCALAR(0x9d1e1d8))
8 (SCALAR(0x9d1e1d8))
9 (SCALAR(0x9d1e1d8))
10 (SCALAR(0x9d1e1d8))
Outside loop i = 0 (SCALAR(0x9d343a0))

foreach循环迭代正常列表值,并将变量VAR依次设置为列表的每个元素。如果变量前面有关键字my,那么它是词汇范围的,因此只在循环中可见否则,该变量隐式地位于循环的局部,并在退出循环时恢复其以前的值。如果该变量以前是用my声明的,则它使用该变量而不是全局变量,但它仍然位于循环的局部。。这种隐式本地化只发生在foreach循环中

要保留
$i
的值,可以使用
C
类似
for
循环

my $i = 0;
for ($i = 5; $i <= 10; $i++) { .. }
my$i=0;

对于($i=5;$i),变量
$i
在foreach范围中重新定义为

foreach $i(5..10){

因此foreach外部的变量不会改变。

根据关于foreach循环的perldoc信息:

foreach循环迭代正常列表值并设置 变量VAR依次为列表中的每个元素。如果 在前面加上关键字my,则在词汇范围内,并且 因此,该变量仅在循环中可见 隐式地局部到循环,并在退出时恢复其以前的值 如果变量先前是用my声明的,则它使用 这个变量代替了全局变量,但它仍然局限于 这种隐式本地化只发生在foreach循环中

如果希望在循环外保留$i的值,则可以在foreach循环调用中省略$i,并使用perl的特殊变量$\uuu,如下所示:

#!/usr/bin/perl

use strict;
use warnings;

my $i = 0;
foreach (5..10){
    print $_."\n";
    $i = $_;
}
print "Outside loop i = $i\n";
五, 6. 7. 8. 9 10
外部循环i=10

在这里,我没有使用foreach my$i。在这种情况下,我可以期望它本地化。但是如果我没有在顶部声明my$i=0,它会抱怨变量没有被声明。@PrgmError提供的链接中提到了你的示例。谢谢。C风格的循环可能不太可读,但我O在您确实希望值持久化时更清晰。但容易通过一个错误来弥补:)请注意,它被本地化到循环的原因是,它实际上是将变量别名化到列表中正在迭代的每个元素(或者在
的情况下模拟该变量。
),不将现有变量依次设置为每个值。旁注,与您的问题无关。既然您提到您是Perl新手,而且为了防止您在这方面已经受到上千次的打击:您应该始终将
使用strict;使用警告
位于您编写的每个Perl脚本的顶部。这两个pragma可以为您节省大量痛苦的调试。这可能是一个重复的解释。正是我想要的。那么这是否意味着在循环退出后没有办法保存foreach循环变量的值呢?如果是这种情况,那么我需要使用另一个变量,并在每次迭代中为其分配循环变量的值。这不是效率低下而且是额外的工作吗?即使您将
foreach
拼写为
for
,也会发生本地化。看起来您需要一个备用变量来获取每次迭代时循环中的
$i
值。@chammu似乎您需要一个辅助变量,关于这一点,我将相应地更新我的答案/从显式命名的变量更改为
$\u
通常被认为是可维护性的倒退。对于
循环或
while
循环使用“C风格”
,可能是解决此问题的更好方法。