您的代码总体上是正确的,但是您需要关闭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.