Perl包含许多魔法变量(也称为"特殊的"或"系统的"),这些变量会影响程序的执行:
$_ — 许多操作符(foreach,map,grep,while <>等)的默认变量。@_ — 子程序内的输入参数数组。%SIG — 操作系统信号处理程序的哈希。my @nums = (1,2,3); foreach (@nums) { $_ *= 2; # 原始数组被修改! } sub show_args { print "First: ", $_[0], " "; } show_args('a','b'); # $_[0] = 'a' $SIG{INT} = sub { print "Caught Ctrl-C "; exit; };
注意:许多魔法变量是隐式修改的;不当使用可能会影响程序的全局状态。
在多个嵌套循环或子程序中,可以安全使用全局变量$_吗?
回答: 不可以,因为嵌套循环或子程序通常会重写$_,导致外部上下文中的值丢失。建议使用显式变量:
foreach my $x (@a) { foreach my $y (@b) { ... } }
故事
在处理大日志的脚本中,使用了while(<FH>) {...}循环。在循环内部调用了一个函数,而该函数又启动了map而没有指定自己的变量,这就破坏了外部循环中的$_,导致跳过行。
故事
在通过%SIG处理信号时,开发者替换了处理程序__DIE__,但没有考虑到这会影响整个进程的行为,包括第三方模块,导致在外部代码出错时出现不可控的终止。
故事
在子程序中通过数组引用(@_)优化参数传递,并尝试直接修改其值而不进行显式复制,导致外部代码中的变量意外改变。