-4

我想评估一个环境变量并将结果设置为一个变量:

$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(); 请注意,以这种方式评估的所有环境变量都是由我在不同的地方设置的,因此我不关心恶意访问以这种方式评估的环境变量。

建议?

4

6 回答 6

13

好吧,当然它什么也没做。

如果您的 ENV 变量包含一半代码的文本,但不是,并且您将生成的字符串提供给将该代码评估为 Perl 的东西,那么当然不会起作用。

您只有 3 个选项:

  1. 以编程方式处理字符串,使其中没有无效的语法
  2. 手动确保您的 ENV 变量不是垃圾
  3. 找到一个不涉及eval但给出正确结果的解决方案。

你也可以抱怨

 $x = ' 

不是有效的代码,因为这基本上就是正在发生的事情。

固定 'QUOTE' 的值以工作的示例

# 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 "$@"' 
# '
于 2009-03-19T12:45:02.340 回答
10

你为什么要eval摆在首位?你应该说

my $x = $ENV{QUOTE};
print "$x\n";

eval就像执行 Perl 代码一样执行字符串,$ENV{QUOTE}我当然希望它不是。这就是 \ 消失的原因。如果您要检查$@变量,您会发现一条错误消息,例如

(eval 1) 第 2 行,EOF 处的语法错误

如果您的环境变量将包含 Perl 应该执行的代码,那么您应该查看Safe模块。它允许您控制可以在其中执行的代码类型,eval这样您就不会意外地执行类似的代码"use File::Find; find sub{unlink $File::Find::file}, '.'"

于 2009-03-19T15:06:33.077 回答
6

评估环境值是非常危险的,如果在污染模式下运行会产生错误。

# purposely broken
QUOTE='`rm system`'

$x=eval($ENV{QUOTE});
print $x;

现在想象一下这个脚本是否以 root 访问权限运行,并被更改为实际删除文件系统。

于 2009-03-19T17:41:13.240 回答
2

肯特的回答虽然在技术上是正确的,但没有抓住重点。解决的办法不是eval更好用,而是根本不用eval

这个问题的症结似乎在于理解是什么eval STRINGeval BLOCK尽管名称相同,但它是完全不同的)。它接受一个字符串并将其作为 Perl 代码运行。99.99% 这是不必要的和危险的,会导致意大利面条代码,你绝对不应该在你的 Perl 编程生涯的早期使用它。你在你爸爸的袜子抽屉里找到了枪。发现它可以在你现在试图用它挂海报的东西上打洞。最好忘记它的存在,你的代码会更好。

$x = eval($ENV{EDITOR});不做你认为它做的事。我什至不必知道你认为它做了什么,你甚至在那里使用它意味着你不知道。我也知道你是在关闭警告的情况下运行的,因为 Perl 会因此而对你大喊大叫。为什么?假设EDITOR设置为/bin/vi. 以上等价于$x = /bin/viwhich 甚至不是有效的 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 命令中使用该引号。我对吗?

于 2009-03-22T18:19:27.633 回答
1

好吧,我猜你可以双重转义 QUOTE 的值,因为你知道它会被eval编辑。

于 2009-03-19T12:41:27.637 回答
1

也许你想要的不是 Perl ,而是像 shell 一样eval评估环境变量。为此,您需要使用反引号。

$x = `$ENV{QUOTE}`
于 2009-03-19T19:58:09.467 回答