【问题标题】:perl eval without blockperl eval 无块
【发布时间】:2014-06-08 22:54:02
【问题描述】:

我正在学习 perl eval。我了解如何使用 eval BLOCK,但我遇到了下面的代码。下面的代码在做什么?

while(<>) {
    eval; 
    warn $@ if $@;
}

【问题讨论】:

    标签: perl eval


    【解决方案1】:
    while(<>) {
    

    这会读取输入,并将其放入变量$_&lt;&gt; 使用的输入首先是 @ARGV(如果您使用参数调用脚本),然后是 STDIN(标准输入)。

    钻石运营商here的信息。

    eval; 
    

    这会评估已读取的行,因为未指定要评估的内容会查看 $_

    warn $@ if $@;
    

    此行将显示出现在$@ 中的警告(如果有)。

    【讨论】:

    • 所以这意味着它将评估来自 的 $_ 的字符串行作为 perl 语句?
    • 它依次评估每一行。例如,如果输入在第一行包含if (1) {,然后在第二行包含print "ok";,在第三行包含},这些都将无法评估。 (不过,Perl 关于读取文件时被视为“行”的概念是configurable。)
    【解决方案2】:

    Perl 的 eval() 内建函数可以使用 BLOCK 或 EXPR。如果给定一个 EXPR,则 EXPR 将被评估为包含要执行的 Perl 代码的字符串。

    例如:

    #!/usr/bin/env perl
    
    use strict;
    use warnings;
    use feature 'say';
    
    eval { say "Hello, Block World!"; };
    
    eval 'say "Hello, String World!";';
    

    此代码按您的预期执行say()s。

    $ ./evals.pl
    Hello, Block World!
    Hello, String World!
    

    一般来说,eval() 的字符串版本被认为是危险的,特别是如果您允许基于来自您控制之外的变量插值到该字符串中。例如:

    #!/usr/bin/env perl
    
    use strict;
    use warnings;
    use feature 'say';
    
    my $name = $ARGV[0] // 'World';
    
    eval "say 'Hello, $name';";
    

    如果这样调用,这段代码是安全的:

    $ ./evals.pl Kaoru
    Hello, Alex
    
    $ ./evals.pl
    Hello, World
    

    但如果用户将其称为:

    $ ./evals.pl "Kaoru'; system 'rm -rf /"
    

    另一方面,在字符串eval() 的支持下,它与Data::Dumper::Dumper() 相反,对于将转储的Perl 代码转换回Perl 内部数据结构非常有用。例如:

    #!/usr/bin/env perl
    
    use strict;
    use warnings;
    use feature 'say';
    
    use Data::Dumper;
    
    my $hashref = { a => 1, b => 2, c => 3 };
    
    print Dumper $hashref;
    
    my $VAR1;
    my $hashref_copy = eval Dumper $hashref;
    
    say $hashref_copy->{b};
    

    正如您所料,输出:

    $ ./evals.pl
    $VAR1 = {
            'c' => 3,
            'b' => 2,
            'a' => 1
            };
    2
    

    请参阅perldoc -f evalhttp://perldoc.perl.org/functions/eval.html 了解更多详情。

    从 Perl 5.16.3 开始,还有一个 evalbytes() 将字符串视为字节字符串而不是字符串。有关字符串和字节字符串之间区别的更多详细信息,请参阅perldoc -f perlunicodehttp://perldoc.perl.org/perlunicode.html

    您明确询问的代码:

    while(<>) {
        eval; 
        warn $@ if $@;
    }
    

    正在读取STDIN 或@ARGV 中指定的文件的每一行,并将每一行输入评估为一行Perl 代码。如果该 Perl 代码编译失败,或通过die() 引发异常,则会向STDERR 发出错误警告。 perldoc -f eval 详细说明了 eval() 如何以及为什么设置 $@

    作为被调用代码的示例:

    $ echo 'print "foo\\n";' | ./evals.pl 
    foo
    
    $ echo 'print 1 + 1, "\\n";' | ./evals.pl
    2
    
    $ echo 'dfsdfsdaf' | ./evals.pl
    Bareword "dfsdfsdaf" not allowed while "strict subs" in use at (eval 1) line 1, <> line 1.
    
    $ echo 'die "dead";' | ./evals.pl 
    dead at (eval 1) line 1, <> line 1.
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-06-13
      • 1970-01-01
      • 1970-01-01
      • 2020-08-24
      • 2021-09-25
      • 1970-01-01
      • 1970-01-01
      • 2021-11-01
      相关资源
      最近更新 更多