如何最好地动态准备和运行用户提供的Perl操作符

时间:2016-02-17 15:58:33

标签: perl dynamic eval

上下文

Perl脚本根据用户提供的 param-file 初始化自身,然后作用于用户提供的 源 - 文件以过滤掉数据并执行其他操作。

param-file 文件包含部分perl表达式,后来假设在运行时期间为eval,例如:

match:!~  col:1  operand:1|2|3
match:=~  col:1  operand:[^123]
match:=!  col:1  operand:^DATE
match:=~  col:1  operand:^(?:\s|DATE)
match:-~  col:1  operand:^\s
match:eq  col:7  operand:CA
match:eq  col:7  operand:DI
match:ne  col:1  operand:ACCOUNT
match:ne  col:1  operand:POSITIONS
match:==  col:8  operand:999
match:!=  col:8  operand:999
嗯,这个怎么样?也许以后,但我也需要它

match="ne list" '11, 71, 7'

简单地说,我的perl将从用户那里获得匹配运算符,然后需要根据其他参数从源文件中过滤掉(或输入)记录。

一种简单的方法是eval

next unless eval "$value $match $operand";

现在,鉴于我知道$match总是相同的,在源文件的每个输入上使用eval听起来有点过分。

if ($match eq '!~')
{
    next unless $value !~ /$operand/o;
}
elsif ($match eq '=~')
{
    next unless $value =~ /$operand/o;
}
elsif ($match eq 'eq')
{
    next unless $value eq $operand;
}
...

我正在考虑进行哈希查找,不知道如何做到这一点。 (我也想知道),还想到关闭......

我正在寻找最好,最有效的方法吗?

1 个答案:

答案 0 :(得分:2)

使用eval EXPR

$match =~ /^(?:[=!][~=]|eq|ne)\z/
   or die("Unrecognized operator \"$match\"\n");

my $rv;
eval("\$rv = \$value $match \$operand; 1")
   or die $@;

使用调度表:

my %ops = (
   '=~' => sub { $_[0] =~ $_[1] },
   '!~' => sub { $_[0] !~ $_[1] },
   '==' => sub { $_[0] == $_[1] },
   '!=' => sub { $_[0] != $_[1] },
   'eq' => sub { $_[0] eq $_[1] },
   'ne' => sub { $_[0] ne $_[1] },
);

my $op = $ops{$match}
   or die("Unrecognized operator \"$match\"\n");

my $rv = $op->($value, $operand);

我不知道闭包有多大用处。