我正在学习perl eval。我理解如何使用eval BLOCK,但我遇到了下面的代码。下面的代码是什么?
while(<>) {
eval;
warn $@ if $@;
}
答案 0 :(得分:1)
while(<>) {
读取输入,并将其放在变量$_
中。 <>
使用的输入是@ARGV
(如果您使用参数调用脚本),则为STDIN(标准输入)。
有关钻石运营商here的信息。
eval;
这会评估已读取的行,因为未指定要评估的内容$_
。
warn $@ if $@;
此行将显示$@
中显示的警告(如果有)。
答案 1 :(得分:0)
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()
。
$ ./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()
中,它可以非常有用,因为它将转储的Perl代码转换回Perl内部数据结构,与Data::Dumper::Dumper()
相反。例如:
#!/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.