【发布时间】:2014-06-08 22:54:02
【问题描述】:
我正在学习 perl eval。我了解如何使用 eval BLOCK,但我遇到了下面的代码。下面的代码在做什么?
while(<>) {
eval;
warn $@ if $@;
}
【问题讨论】:
我正在学习 perl eval。我了解如何使用 eval BLOCK,但我遇到了下面的代码。下面的代码在做什么?
while(<>) {
eval;
warn $@ if $@;
}
【问题讨论】:
while(<>) {
这会读取输入,并将其放入变量$_。 <> 使用的输入首先是 @ARGV(如果您使用参数调用脚本),然后是 STDIN(标准输入)。
钻石运营商here的信息。
eval;
这会评估已读取的行,因为未指定要评估的内容会查看 $_。
warn $@ if $@;
此行将显示出现在$@ 中的警告(如果有)。
【讨论】:
if (1) {,然后在第二行包含print "ok";,在第三行包含},这些都将无法评估。 (不过,Perl 关于读取文件时被视为“行”的概念是configurable。)
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 eval 或http://perldoc.perl.org/functions/eval.html 了解更多详情。
从 Perl 5.16.3 开始,还有一个 evalbytes() 将字符串视为字节字符串而不是字符串。有关字符串和字节字符串之间区别的更多详细信息,请参阅perldoc -f perlunicode 或http://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.
【讨论】: