Perl eval函数

 eval EXPR
eval 表达式
       eval BLOCK

eval 代码块

       eval    In the first form, the return value of EXPR is parsed and exe-
               cuted as if it were a little Perl program.  The value of the
               expression (which is itself determined within scalar context)
               is first parsed, and if there weren’t any errors, executed in
               the lexical context of the current Perl program, so that any
               variable settings or subroutine and format definitions remain
               afterwards.  Note that the value is parsed every time the
               "eval" executes.  If EXPR is omitted, evaluates $_.  This form
               is typically used to delay parsing and subsequent execution of
               the text of EXPR until run time.

在第一种形式中,表达式的返回值是解析和执行就好像它是一个小的Perl程序。

表达式的值(这本身就是在标量上下文确定)
首先解析,如果这里没有错误,执行当前的PERL程序的文本,使任何变量设置或者子函数和格式定义保持向后

注意每次eval执行变量都会解析,如果表达式省略,执行$_.
这种形式通常用于延迟解析和随后的文本表达式的执行


执行动态代码:
use strict;
use warnings;

sub test {
    my $num1 = 2;
    my $num2 = 3;

    foreach my $op (qw!+ - * /!) {
        print "$num1 $op $num2 equals ";
        #print eval "$num1 $op $num2", "
";
        print  "$num1 $op $num2", "
";
    }
}

test()
[oracle@june3 dbi]$ perl 3.pl
2 + 3 equals 2 + 3
2 - 3 equals 2 - 3
2 * 3 equals 2 * 3
2 / 3 equals 2 / 3
#################################################
[oracle@june3 dbi]$ cat 3.pl 
use strict;
use warnings;

sub test {
    my $num1 = 2;
    my $num2 = 3;

    foreach my $op (qw!+ - * /!) {
        print "$num1 $op $num2 equals ";
        #print eval "$num1 $op $num2", "
";
        print eval  "$num1 $op $num2", "
";
    }
}

test()
[oracle@june3 dbi]$ perl 3.pl 
2 + 3 equals 5
2 - 3 equals -1
2 * 3 equals 6
2 / 3 equals 0.666666666666667



               In the second form, the code within the BLOCK is parsed only
               once--at the same time the code surrounding the "eval" itself
               was parsed--and executed within the context of the current Perl
               program.  This form is typically used to trap exceptions more
               efficiently than the first (see below), while also providing
               the benefit of checking the code within BLOCK at compile time.

第2种情况,块内的代码只解析一次,同时围绕着"eval"的代码本身被解析和执行

这种情况通常用于更高效的捕捉异常,也提供了检查代码块在编译事件的好处。



               The final semicolon, if any, may be omitted from the value of
               EXPR or within the BLOCK.


最后的分号,可以从表达式或者代码块省略

               In both forms, the value returned is the value of the last
               expression evaluated inside the mini-program; a return state-
               ment may be also used, just as with subroutines.  The expres-
               sion providing the return value is evaluated in void, scalar,
               or list context, depending on the context of the "eval" itself.
               See "wantarray" for more on how the evaluation context can be
               determined.

所有两种情况,返回值是程序里最后执行表达式返回的值;一个返回状态也被使用,就像子程序。

表达式提供的返回值是计算无效的,变量或者列表上下文。依赖于eval的上下文







               If there is a syntax error or runtime error, or a "die" state-
               ment is executed, an undefined value is returned by "eval", and
               $@ is set to the error message.  If there was no error, $@ is
               guaranteed to be a null string.  Beware that using "eval" nei-
               ther silences perl from printing warnings to STDERR, nor does
               it stuff the text of warning messages into $@.  To do either of
               those, you have to use the $SIG{__WARN__} facility, or turn off
               warnings inside the BLOCK or EXPR using "no warnings 'all'".
               See "warn", perlvar, warnings and perllexwarn.


如果这里有个符号错误或者是runtime错误,或者die语句被执行,一个没有定义的值通过eval返回

   $@ 存储了错误信息,如果没有错误 $@是强制为空字符窜。小心 使用eval 既不打印错误到STDERR 也不将错误写入到$@






               Note that, because "eval" traps otherwise-fatal errors, it is
               useful for determining whether a particular feature (such as
               "socket" or "symlink") is implemented.  It is also Perl’s
               exception trapping mechanism, where the die operator is used to
               raise exceptions.

         因为eval 捕捉另外一些致命的错误,对那些特定的功能包括( "socket" or "symlink")是有效的

也用于Perl捕获异常机制,




               If the code to be executed doesn’t vary, you may use the eval-
               BLOCK form to trap run-time errors without incurring the
               penalty of recompiling each time.  The error, if any, is still
               returned in $@.  Examples:


  如果执行代码没有变化,你可以使用eval块去捕捉运行时候的错误,而不需要每次重复的编译  错误存储到$@

                   # make divide-by-zero nonfatal
                   eval { $answer = $a / $b; }; warn $@ if $@;


                   # same thing, but less efficient
                   eval ’$answer = $a / $b’; warn $@ if $@;


                   # a compile-time error
                   eval { $answer = };                 # WRONG


                   # a run-time error
                   eval ’$answer =’;   # sets $@

               Using the "eval{}" form as an exception trap in libraries does
               have some issues.  Due to the current arguably broken state of
               "__DIE__" hooks, you may wish not to trigger any "__DIE__"
               hooks that user code may have installed.  You can use the
               "local $SIG{__DIE__}" construct for this purpose, as shown in
               this example:

                   # a very private exception trap for divide-by-zero
                   eval { local $SIG{’__DIE__’}; $answer = $a / $b; };
                   warn $@ if $@;

               This is especially significant, given that "__DIE__" hooks can
               call "die" again, which has the effect of changing their error
               messages:

                   # __DIE__ hooks may modify error messages
                   {
                      local $SIG{’__DIE__’} =
                             sub { (my $x = $_[0]) =~ s/foo/bar/g; die $x };
                      eval { die "foo lives here" };
                      print $@ if $@;                # prints "bar lives here"
                   }

               Because this promotes action at a distance, this counterintu-
               itive behavior may be fixed in a future release.

               With an "eval", you should be especially careful to remember
               what’s being looked at when:

                   eval $x;            # CASE 1
                   eval "$x";          # CASE 2

                   eval ’$x’;          # CASE 3
                   eval { $x };        # CASE 4

                   eval "$$x++";      # CASE 5
                   $$x++;              # CASE 6

               Cases 1 and 2 above behave identically: they run the code con-
               tained in the variable $x.  (Although case 2 has misleading
               double quotes making the reader wonder what else might be hap-
               pening (nothing is).)  Cases 3 and 4 likewise behave in the
               same way: they run the code '$x', which does nothing but return
               the value of $x.  (Case 4 is preferred for purely visual rea-
               sons, but it also has the advantage of compiling at compile-
               time instead of at run-time.)  Case 5 is a place where normally
               you would like to use double quotes, except that in this par-
               ticular situation, you can just use symbolic references
               instead, as in case 6.

               "eval BLOCK" does not count as a loop, so the loop control
               statements "next", "last", or "redo" cannot be used to leave or
               restart the block.

               Note that as a very special case, an "eval ''" executed within
               the "DB" package doesn’t see the usual surrounding lexical
               scope, but rather the scope of the first non-DB piece of code
               that called it. You don’t normally need to worry about this
               unless you are writing a Perl debugger.


1.
eval 这块代码真的诱发了常见错误,就会停止运行,但不至于使程序崩溃.

[oracle@dwh1 dbi]$ cat 1.pl 1.pl 
eval{$var = 2 / 0;
};
print "An error occurred: $@" if $@;
print "bbbb
";
eval{$var = 2 / 0;
};
print "An error occurred: $@" if $@;
print "bbbb
";
[oracle@dwh1 dbi]$ perl 1.pl
An error occurred: Illegal division by zero at 1.pl line 1.
bbbb


程序崩溃,下面的没在继续执行


[oracle@dwh1 dbi]$ cat 1.pl 
{$var = 2 / 0;
};
print "An error occurred: $@" if $@;
print "bbbb
";


[oracle@dwh1 dbi]$ perl 1.pl 1.pl 
Illegal division by zero at 1.pl line 1.


2.

eval 同时也是一个块结构

foreach my $person (qw/fred wilma betty barney dino pebbles/) {
eval {
 open FILE ,"<$person" or die "Can't open file '$person':$!";

my($total,$count);


while (<FILE>) {
$total += $_;
$count++;
}

my $average = $total/$count;
print "Average for file $person was $average
";

&do_something($person,$average);
print "2-------over
";
};
if ($@) {
print "An error occurred($@),continuing
";
 }
print "3-------over
";
}


如果错误在处理某个文件的时候发生,我们会获得错误信息,不过程序会跳过剩下的步骤,接着处理下一个文件。



[oracle@dwh1 dbi]$ cat 3.pl 
eval{$var = 2 / 1;
    print "$war is $var
";
   open FILE ,"aa" or die "Can't open file '$person':$!";
  print "1------test
";

};
print "An error occurred: $@" if $@;
print "bbbb
";
[oracle@dwh1 dbi]$ perl 3.pl 
$war is 2
An error occurred: Can't open file '':No such file or directory at 3.pl line 3.
bbbb


eval 程序哪里发生错误,就在哪里停止
























原文地址:https://www.cnblogs.com/hzcya1995/p/13351877.html