有一些代码看上去很平常,但是却含有潜在的危险,一旦某种条件不对就会使程序中断,过早地结束程序。
my $average = $total / $count; # 除数为零
print "okayn" unless /$match/; # 正则表达式不合法
open MINNOW,‘>ship.txt’or die "Can‘t create ‘ship.txt’: $!"; # 文件句柄打开失败
&implement($) foreach @rescue_scheme; # 调度子程序报错
可是,不能因为代码的某一片断出错而使我们的整个程序崩溃。Perl用 eval 操作符来实现捕捉错误的机制。如果在eval块里代码发生错误,系统会退出这个块,继续执行eval代码块之外的代码。
检查一下$@变量,此变量为空(表示没有出错)或者代码出错时系统返回的“遗言”,多半是“除零错误”之类错误。
eval { $average = $total / $count } ;print "Continuing after error: $@" if $@;
eval { &rescue_scheme_42 } ;print "Continuing after error: $@" if $@;
注意:
1、eval块的结尾必须有分号,因为不像 if或者while那样的控制结构,eval实际上是个函数。
2、可以设置词法变量("my" 修饰的变量)和另外其它的断言语句。
3、eval有像子例程那样的返回值(最后一个表达式的求值结果,或者由return语句返回的结果)。 eval代码块执行失败就没有值返回;如果在标量环境将返回未定义值,在列表环境将返回一个空的列表。
4、Perl也支持eval代码块的嵌套,eval捕捉代码运行是错误,在perl脚本发生严重错误时,perl脚本会自动中断执行,eval不能捕捉这些错误,如内存溢出或其它的灾难,语法错误也不在eval的工作范围之内,在编译检查时,语法错误就会被检查出,eval也不能捕捉警告,但可以参考变量$SIG{__WARN_}
因此,比较安全的求平均值的代码的写法如下:
my $average = eval { $total / $count } ;
二、用eval动态编译代码
eval有另外一种用法,其参数是作为一个字符串表达式,而不是代码块。在运行时,它将字符串临时编译成代码并且执行。这很易用,但也很危险,因为有可能会把具有危害性的代码放到字串里。
eval ‘$sum = 2 + 2′;
print "The sum is $sumn";
Perl在词法环境中执行那段代码,这意味着我们好像在执行的时候输入这些代码的一样。eval的结果就是最后一个表达式求值的值,所以我们不必在eval中输入整个语句。
#!/usr/bin/perl
foreach my $operator ( qw(+ – * /) ) {
my $result = eval "2 $operator 2";
print "2 $operator 2 is $result\n";
}
解释:上述例子中,依次将加减乘除四个操作符动态使用到eval代码块中,foreach循环分别将四个操作符赋值给$operator,eval代码块的执行结果返回给$result
但此时可能会遇到分母缺失的情况
print ‘The quotient is ‘, eval ’5 /’, "n";
warn $@ if $@;
eval 捕捉语法错误,然后在我们调用eval后,在检查$@值时,把出错信息放到变量$@中