感谢IT牛人博客聚合上还能找到我之前博客的一些内容,因为之前主机没续费等各种原因,也懒得翻之前的备份文档了,就把那上面的文章直接拷过来整理一下好了,只搬迁一些还有意义的内容好了,其他的就让它随风而去吧。
Perl有很多语法糖,可以帮助我们用很少的代码表达更多的意思,其中就包括了Perl的各种内置变量。例如我们今天的主角$_
。
$_
代表循环中的当前元素,我一直以为$_
是一个值copy,而且隐约记得小骆驼里说过,当嵌套循环时,内层$_
会覆盖外层$_
的值,但是当内层循环结束时,$_
会恢复成原来的值。一直这么用相安无事,直到今天遇到了bad case,例如:
my @ins = @ARGV;
foreach(@ins) {
open IN, $_;
while(my $line = chomp ) {
print "@ins\n";
}
close IN;
}
程序很简单,输入一组文件,然后读取他们的内容。注意到那条打印语句,按我想要的是@ins数组内插,也就是它的元素。但实际上打印出的却是读入的文件的内容。而在内层while循环结束后@ins数组完全被改变了。
百思不得其解,按道理说没有任何语句改变了@ins数组的值,但是它却真的变了。周围找不到人问,于是加了Perl的beginners邮件列表,问了这个问题。
总结起来原因是这样的,是内层的$_
改变了外层循环的$_
值,也就是改变了@ins
数组的值。小骆驼那句话说的有问题?其实没错,只是$_
会自动恢复发生在foreach嵌套foreach上,而当内层循环是while时,就不会自动恢复。那我想保留外层数组就只能copy一个?其实不是的,只要不用语法糖,显示的声明lexical variable就可以了。因此只要修改上述代码即可:
my @ins = @ARGV;
foreach my $file (@ins) {
open $in, ') {
chomp;
print "@ins\n";
}
close $in;
}
这样就能达到我们想要的效果,在open语句的格式上,maillist上面的朋友说用3个参数的比较好,因此帮我改了。另外,Shawn指出,实际上$_
并不是foreach的element的值拷贝,而是真正代表数组的元素,也就是说当内层循环是while时,实际上执行了$_ = current_line
的操作,因此会改变数组的值。
今晚收获颇丰,作为一个才写了两个月Perl的人,还是老老实实用显示变量吧,在不清楚Perl内部实际怎么用那些语法糖前,还是少用为妙。糖是甜的,但是吃多了蛀牙还长胖。