【问题标题】:Perl passing argument into evalPerl 将参数传递给 eval
【发布时间】:2012-10-04 10:13:03
【问题描述】:

我在使用 eval 函数时遇到问题。

确实,我在 SQL 数据库中有一些函数名,我的目标是在 perl 中执行这些函数(在 SQL 中检索之后)。

考虑到 $RssSource->{$k}{Proceed} 包含“&test”作为从 SQL 检索的字符串,这就是我正在做的事情:

my $str2 = "ABCD";
eval "$RssSource->{$k}{Proceed}";warn if $@;

sub test
{
   my $arg = shift;

   print "fct TEST -> ", $row, "\n";
}

这工作正常并显示:

fct TEST ->

但是我希望能够将 $str2 作为参数传递给 $RssSource->{$k}{Proceed} 但我不知道如何,我尝试的每个语法都返回错误:

eval "$RssSource->{$k}{Proceed}$str2"
eval "$RssSource->{$k}{Proceed}($str2)"
eval "$RssSource->{$k}{Proceed}"$str2
eval "$RssSource->{$k}{Proceed}"($str2)

有人可以告诉我如何正确地将参数传递给评估函数吗?

非常感谢您的帮助

问候。

弗洛伦特

【问题讨论】:

  • 您是说$arg 而不是$row,还是相反?
  • 是的,你是对的,我在发布之前重写了我的代码以严格关注我的问题,并且没有在测试函数中正确更改变量名,对不起

标签: perl arguments eval


【解决方案1】:

我将假设$RssSource->{$k}{Proceed} 始终包含name&name,否则您的要求没有多大意义。

my $func_name = $RssSource->{$k}{Proceed};
$func_name =~ s/&//;
my $func_ref = \&$func_name;    # Works with strict on!
$func_ref->(@args);

如果你想添加一些错误检查,下面会检查sub是否可以被调用:

defined(&$func_ref)

【讨论】:

  • 第 3 行不只是引用了一个名为“func_name”的子组件吗?
  • @Dondi Michael Stroma,哎呀,是的!固定。
  • 非常感谢池上,看起来是最好的方法,感谢您对错误检查的评论!
【解决方案2】:

如果您evaling 的字符串始终是子调用,您可以通过以下方式之一构造eval 字符串:

$RssSource->{$k}{Proceed} . '($str2)'

(最一般的),或

$RssSource->{$k}{Proceed} . "(\"$str2\")"

(不优雅)

以下是您的解决方案遇到的问题:

eval "$RssSource->{$k}{Proceed}$str2" 的计算结果为 eval "&testABCD"。此子不存在。

eval "$RssSource->{$k}{Proceed}($str2)" 的计算结果为 "&test(ABCD)"。不允许使用裸词。

eval "$RssSource->{$k}{Proceed}"$str2 字符串后面必须跟某种运算符,而不是另一个变量。

eval "$RssSource->{$k}{Proceed}"($str2) 您正试图将字符串作为函数调用。 Perl 不支持此功能。

【讨论】:

  • 感谢您的分析和回答阿蒙,这真的有助于理解我做错了什么
【解决方案3】:

如果您可以将数据库中的数据更改为仅包含函数名称,即test 而不是&test,则可以通过符号引用而不是使用 eval 来调用函数:

$fn="test";
&{$fn}("argument")

【讨论】:

  • 非常感谢 EVil Otto,你说得对,eval 函数不是要走的路
【解决方案4】:

如您所说,如果您的数据库仅包含函数名称,则不需要 eval。您可以将它们用作符号引用(但请删除 &)。现代的方法不是使用 & 来取消引用它,而是使用箭头运算符:

{
    no strict 'refs'; # hopefully you have strict on already...
    $RssSource->{$k}{Proceed}->($str2);
}

【讨论】:

  • 感谢 Dondi,我不得不承认,初读时我更喜欢 Ikegami 的答案,它与严格的 ref 兼容。你能告诉我为什么你说这是实现这一目标的现代方式吗?
  • @ehretf ikegami 的回答很好,实际上他最后确实使用了箭头运算符。我添加了自己的答案,因为他最初有一个错误。现在它已经修复了,我会给它一个赞成票;)
【解决方案5】:

很像ikegami的回答,使用can的方法,比较符合我的口味。蒂姆托迪。

my $func_name = $RssSource->{$k}{Proceed};
$func_name =~ s/&//;
my $func_ref = __PACKAGE__->can($func_name)
  or die "No function named $func_name";
$func_ref->(@args);

【讨论】:

  • 谢谢 Joel,can 方法看起来很有趣!
猜你喜欢
  • 2014-02-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-11-03
  • 1970-01-01
  • 1970-01-01
  • 2021-03-09
相关资源
最近更新 更多