【问题标题】:How can I eval environment variables in Perl?如何在 Perl 中评估环境变量?
【发布时间】:2010-10-14 07:21:03
【问题描述】:

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

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

建议?

【问题讨论】:

  • 您真正想要完成什么?问这个问题,也许我们可以给你更好的帮助。 :)
  • 不要盲目评估 %ENV 用户输入;这是非常危险的。 eval 调用 perl 解释器并且 %ENV 已经是有效的 perl 标量。它充其量不会做任何事情,而最坏的情况可能会造成巨大的伤害。任何人都可以将代码放入 EDITOR 以破坏您的系统或破坏敏感数据,无论您是否属于。
  • 老实说,这是我想问的问题。我控制这个过程使用的环境变量的值(因此我不会盲目地评估环境,因为它之前是由“我”设置的)。我需要评估许多不同的东西,这只是一个。我相信我有一个充分的答案。谢谢
  • 你为什么要调用 eval() 呢?你认为 eval() 有什么作用?

标签: perl environment-variables


【解决方案1】:

好吧,我猜你可以双重转义 QUOTE 的值,因为你知道它将是evaled。

【讨论】:

  • 这就像说“你应该把解药和你要喝的毒药一起吃”。不要喝毒药!
【解决方案2】:

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

如果您的 ENV 变量包含一半代码的文本,但不是,并且您将生成的字符串提供给 eval将该代码视为 Perl 的东西,课程它不会工作。

你只有三个选择:

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

【讨论】:

  • 这一切都很好,但他根本不应该使用 eval() !这是非常危险的,对手头的任务完全没有必要。 OP 显然不明白它的作用。
  • @Schwern 我完全同意,我不建议人们使用 eval ,即使他们认为他们知道自己在做什么,我通常认为他们只是没有认真考虑过足够的。但给出的答案是基于我不知道他实际上在做什么的事实。
【解决方案3】:

为什么你首先eval'ing?你应该说

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

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

的错误消息

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

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

【讨论】:

    【解决方案4】:

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

    # purposely broken
    QUOTE='`rm system`'
    

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

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

    【讨论】:

      【解决方案5】:

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

      $x = `$ENV{QUOTE}`
      

      【讨论】:

      • 不应该是 $x = echo -n \$QUOTE;?
      • 作为一个环境变量,大概它已经通过 shell 运行了,所以我怀疑这就是 OP 试图做的事情。我也无法理解您为什么想知道 shell 如何看到引号字符。
      【解决方案6】:

      肯特的回答虽然在技术上是正确的,但没有抓住重点。解决方法是不要使用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 命令中使用该引号。我说的对吗?

      【讨论】:

      • +1,当然,完全正确,我只是假设他在做一些特别的事情,因为我们没有看到“真实”的 ENV 变量只是过度简化的变量。另外,由于没有运行代码,我没有注意到警告问题,所以假设他的 EDITOR 中没有引号,你的答案会更好
      猜你喜欢
      • 2011-07-04
      • 2021-08-28
      • 2020-07-12
      • 2016-08-27
      • 2020-11-17
      • 1970-01-01
      • 2020-11-16
      • 2011-10-15
      • 2018-01-15
      相关资源
      最近更新 更多