我正在用Perl编写一个脚本,并对Perl的foreach
构造有疑问.
看来,如果你更改其中一个循环变量,它会在实际数组中发生变化.这其实是这样,还是我做的东西完全错了吗?
我想换一个字符串喜欢abc.abc#a
到abc_abc_a
(强调了非字母数字字符),但我需要的阵列以备后用在保留原始值.
我的代码看起来像这样:
@strings = ('abc.abc#a', 'def.g.h#i');
foreach my $str (@strings){
$str =~ s/[^0-9A-Za-z]/_/g;
print $str, "\n"; #Actually I use the string to manipulate files.
}
Run Code Online (Sandbox Code Playgroud)
我可以通过执行以下操作来解决问题:
@strings = ('abc.abc#a', 'def.g.h#i');
foreach my $str (@strings){
my $temp = $str; #copy to a temporary value
$temp =~ s/[^0-9A-Za-z]/_/g;
print $temp, "\n"; #$str remains untouched...
}
Run Code Online (Sandbox Code Playgroud)
但有没有更有效的方法来实现这一目标?
非常感谢你!
Eth*_*her 16
你不是疯了; 这是正常的行为.参见Foreach循环下的perldoc perlsyn:
如果LIST的任何元素是左值,您可以通过修改循环内的VAR来修改它.相反,如果LIST的任何元素不是左值,则任何修改该元素的尝试都将失败.换句话说,"foreach"循环索引变量是您循环的列表中每个项目的隐式别名.
其他循环迭代器(如map)具有类似的行为:
Run Code Online (Sandbox Code Playgroud)map BLOCK LIST map EXPR,LIST
...
请注意,$ _是列表值的别名,因此可用于修改LIST的元素.虽然这很有用并且受到支持,但如果LIST的元素不是变量,它可能会导致奇怪的结果.在大多数情况下,为此目的使用常规的"foreach"循环将更加清晰.另请参阅"grep"以获取由BLOCK或EXPR计算为true的原始列表中的那些项组成的数组.
您可以通过这种方式重写代码,这至少可以避免添加额外的行:
my @strings = ('abc.abc#a', 'def.g.h#i');
foreach my $str (@strings){
(my $copy = $str) =~ s/[^0-9A-Za-z]/_/g;
print $copy, "\n";
}
Run Code Online (Sandbox Code Playgroud)