我想评估环境变量并将结果设置为变量:
$x=eval($ENV{EDITOR});
print $x;
输出:
/bin/vi
工作正常。
如果我将环境变量QUOTE设置为\'并尝试相同的操作:
$x=eval($ENV{QUOTE});
print $x;
输出:
(无)
$@ set to: "Can't find a string terminator anywhere before ..."
我不想简单地设置$x=$ENV{QUOTE};
,因为eval也用于调用脚本并返回其最后一个值(非常方便),所以我想坚持使用eval();请注意,以这种方式评估的所有环境变量都是由我在不同的地方设置的,所以我不关心恶意访问以这种方式评估的环境变量。
建议?
答案 0 :(得分:13)
嗯,当然它什么都不做。
如果您的ENV变量包含的文本是半码但不是,并且您将结果字符串提供给 eval 的代码为Perl的代码, course 它不会起作用。
您只有3个选项:
你也可以抱怨
$x = '
不是有效的代码,因为这基本上是正在发生的事情。
# Bad.
QUOTE="'" perl -wWe 'print eval $ENV{QUOTE}; print "$@"'
# Can't find string terminator "'" anywhere before EOF at (eval 1) line 1.
# Bad.
QUOTE="\'" perl -wWe 'print eval $ENV{QUOTE}; print "$@"'
# Can't find string terminator "'" anywhere before EOF at (eval 1) line 1.
# Bad.
QUOTE="\\'" perl -wWe 'print eval $ENV{QUOTE}; print "$@"'
# Can't find string terminator "'" anywhere before EOF at (eval 1) line 1.
# Good
QUOTE="'\''" perl -wWe 'print eval $ENV{QUOTE}; print "$@"'
# '
答案 1 :(得分:10)
你为什么首先eval
?你应该说
my $x = $ENV{QUOTE};
print "$x\n";
eval
正在执行$ENV{QUOTE}
中的字符串,就像它是Perl代码一样,我当然希望它不是。这就是\消失的原因。如果您要检查$@
变量,则会发现错误消息,如
在EOF处的(eval 1)第2行的语法错误
如果环境变量将包含Perl应该执行的代码,那么您应该查看Safe模块。它允许您控制eval
中可以执行的代码类型,这样您就不会意外地执行"use File::Find; find sub{unlink $File::Find::file}, '.'"
答案 2 :(得分:6)
评估环境值是非常危险,如果在污点模式下运行会产生错误。
# purposely broken
QUOTE='`rm system`'
$x=eval($ENV{QUOTE});
print $x;
现在想象一下,如果此脚本是以root访问权限运行的,并且已更改为实际删除文件系统。
答案 3 :(得分:2)
肯特的回答虽然在技术上是正确的,却忽略了这一点。解决方案不是更好地使用eval
,而是根本不使用eval
!
这个问题的关键在于理解eval STRING
的作用(尽管名称相同,但eval BLOCK
完全不同)。它需要一个字符串,将其作为Perl代码运行。 99.99%这是不必要和危险的,并导致意大利面条代码,你绝对不应该在你的Perl编程生涯中这么早使用它。你在你父亲的袜子抽屉里找到了枪。发现它可以在你现在试图用它悬挂海报的东西上打洞。最好忘记它存在,你的代码会更好。
$x = eval($ENV{EDITOR});
没有按照您的想法行事。我甚至不知道你认为它做了什么,你甚至在那里使用它意味着你不知道。我也知道你正在关闭警告,因为Perl会为此向你尖叫。为什么?我们假设EDITOR
设置为/bin/vi
。以上等同于$x = /bin/vi
,它甚至不是有效的Perl代码。
$ EDITOR=/bin/vi perl -we '$x=eval($ENV{EDITOR}); print $x'
Bareword found where operator expected at (eval 1) line 1, near "/bin/vi"
(Missing operator before vi?)
Unquoted string "vi" may clash with future reserved word at (eval 1) line 2.
Use of uninitialized value $x in print at -e line 1.
我不确定你是如何让它首先工作的。我怀疑你遗漏了你的例子。也许调整EDITOR直到它工作?
您无需做任何神奇的事情来阅读环境变量。只需$x = $ENV{EDITOR}
。完成。 $x
现在/bin/vi
正如您所愿。它与$x = $y
相同。与QUOTE相同。
$ QUOTE=\' perl -wle '$x=$ENV{QUOTE}; print $x'
'
完成。
现在,我怀疑你真正想要做的是运行该编辑器并在一些shell命令中使用该引用。我是对的吗?
答案 4 :(得分:1)
嗯,我猜你可以双重转义QUOTE的值,因为你知道它会被eval
编辑。
答案 5 :(得分:1)
也许你想要的不是Perl的eval
,而是评估环境变量,因为shell会。为此,您需要使用反引号。
$x = `$ENV{QUOTE}`