是否有任何用例需要在Perl中使用字符串eval?

时间:2010-02-23 13:36:55

标签: perl eval

您是否可以提供真正需要使用eval EXPR的示例? 我问,因为它通常气馁。

4 个答案:

答案 0 :(得分:6)

String eval是唯一的方法:

  1. 在运行时决定的包中执行新代码
  2. 在运行时向包中添加重载(至少根据overload.pm)
  3. 执行Perl的任意字符串
  4. 编译宏类型替换
  5. 不应将字符串eval用于:

    1. 评估符号引用
    2. 执行用户的任何代码
    3. 陷阱错误
    4. 如果有其他方法可以做到这一点
    5. eval还可用于在不同系统或不同语言之间创建ad-hoc通信协议,这些协议也具有eval(前提是当然一切都是安全的.JSON可以被视为此方法的更安全但有限的子集)

答案 1 :(得分:5)

String eval是用字符串创建新代码的唯一方法。这很少是必要的,但是有一些有效的用例,例如将模板转换为可运行的代码时。除此之外,它的有效用途很少。 eval "require $module_name"是一个众所周知的习惯用法,但使用例如Module::Load比IMO更好。

答案 2 :(得分:4)

eval EXPR可以用于元编程,以防你不能 依靠Moose或类似的 用于动态创建类的框架。看看源头 Exception::Class 看到这种技术的完全恐怖。

附录:(@ friedo)
eval提供的一个功能是符号表操作 能够使用SUPER并使其按预期工作:

package Foo;
sub msg { return 'Foo' }

package MyCodeGenerator;

use strict;
use warnings;

eval <<'EOPERL'; # '' -> no variable interpolation
  package FooBar;
  @FooBar::ISA = qw/Foo/;
  sub msg {
    my $self = shift;
    return $self->SUPER::msg() . 'Bar'; # calls &Foo::msg
  }
EOPERL

虽然这会(希望)在运行期间死亡,或者为你做准备 长达数小时的调试会话:

package BROKEN_Generator;

@FooBar::ISA = qw/Foo/;
*{'FooBar::msg'} = sub {
  my $self = shift;
  return $self->SUPER::msg() . 'Bar'; # tries to call &BROKEN_Generator::msg
}

轻松访问Top 5 of things I hate about Perl

答案 3 :(得分:0)

几年前,我写了一个静态网站生成器,它使用Perl(有趣的是我的拼写检查器建议“Peril”作为替代)作为其脚本语言。它允许用户输入关于层次结构的不同级别的信息 - 首先进入市场的是一个墓地,在那里你有客户(付费客户)拥有纪念物(显然是死者)。

它有一个GUI,您可以在其中输入变量,例如(在我的图形技能上颤抖):

+------------+----------------------------+
| ClientName | Pax Diablo                 |
+------------+----------------------------+
| Address    | 666 Hades St, Washinton DC |
+------------+----------------------------+

和图片变量。

此外,对于每个市场(例如上述墓地),有一个控制脚本,它基本上运行并处理多个层级的每个记录以生成静态内容。在此之前,该程序已将所有这些变量转换为:

$Var{"ClientName"} = "Pax Diablo";

(我认为语法是正确的,我暂时没有做任何Perl开发)。最终的结果是一个完整的网站,有很多客户,很多纪念馆,搜索页面和一个不错的小钱赚钱的人一直持续(我被葬礼总监吹出市场,提供与“免费”服务相同的东西他们的常规套餐。)

但是整个事情基本上是用最小的Perl编写的,只做了两件事:

  • 将变量转换为Perl赋值语句;和
  • 运行特定于市场的Perl代码。

赋值语句的执行和特定于市场的Perl代码都是使用eval完成的。

所以它并不像你想象的那么无用。这是一种将脚本引入应用程序的廉价方法。