如何在Perl中评估环境变量?

时间:2009-03-19 12:35:42

标签: perl environment-variables

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

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

建议?

6 个答案:

答案 0 :(得分:13)

嗯,当然它什么都不做。

如果您的ENV变量包含的文本是半码但不是,并且您将结果字符串提供给 eval 的代码为Perl的代码, course 它不会起作用。

您只有3个选项:

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

     $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 "$@"' 
    # '
    

答案 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}`