假设我有一个包含所有子程序名称的数组,我想逐个调用。
foreach $sub (@arr){
print "Calling $sub\n";
#---How to call $sub?----
&$sub; ## will not work
}
答案 0 :(得分:10)
您的代码通常是正确的,但您需要关闭strict 'refs'
以使Perl允许您将变量内容用作代码引用。
use strict;
use warnings;
sub foo { print "foo" }
sub bar { print "bar" }
my @arr = qw/foo bar/;
foreach my $sub (@arr) {
no strict 'refs';
print "Calling $sub\n";
&$sub();
}
这里的输出是:
Calling foo
fooCalling bar
bar
我在调用后还添加了括号()
。这样我们就不会向%$sub
传递任何参数。如果我们不这样做,将使用当前子例程的@_
参数列表。
但是,您可能不应该这样做。特别是如果@arr
包含用户输入,这是一个大问题。您的用户可以注入代码。考虑一下:
my @arr = qw/CORE::die/;
现在我们得到以下输出:
Calling CORE::die
Died at /home/code/scratch.pl line 1492.
糟糕。你不想这样做。 die
示例并不是很糟糕,但是像这样你可以轻松地在一些不合适的包中调用代码。
制作dispatch table可能更好。关于Mark Jason Dominus的 Higher Order Perl 中有一整章,你可以download for free on his website。
它基本上意味着您将所有subs作为代码引用放入哈希,然后在循环中调用它们。这样你就可以控制哪些是允许的。
use strict;
use warnings;
sub baz { print "baz" }
my %dispatch = (
foo => sub { print "foo" },
bar => sub { print "bar" },
baz => \&baz,
);
my @arr = qw/foo bar baz wrong_entry/;
foreach my $sub ( @arr ) {
die "$sub is not allowed"
unless exists $dispatch{$sub};
$dispatch{$sub}->();
}
输出:
foobarbaz
wrong_entry is not allowed at /home/code/scratch.pl line 1494.
答案 1 :(得分:7)