Raj*_*Raj 5 perl call subroutine
假设我有一个包含所有子程序名称的数组,我想逐个调用.
foreach $sub (@arr){
print "Calling $sub\n";
#---How to call $sub?----
&$sub; ## will not work
}
Run Code Online (Sandbox Code Playgroud)
sim*_*que 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();
}
Run Code Online (Sandbox Code Playgroud)
这里的输出是:
Calling foo
fooCalling bar
bar
Run Code Online (Sandbox Code Playgroud)
我还在()通话后添加了括号.这样我们就不会传递任何参数%$sub.如果我们不这些,@_将使用当前子例程的参数列表.
但是,你可能不应该这样做.特别是如果@arr包含用户输入,这是一个大问题.您的用户可以注入代码.考虑一下:
my @arr = qw/CORE::die/;
Run Code Online (Sandbox Code Playgroud)
现在我们得到以下输出:
Calling CORE::die
Died at /home/code/scratch.pl line 1492.
Run Code Online (Sandbox Code Playgroud)
哎呀.你不想这样做.这个die例子并不是很糟糕,但是像这样你可以很容易地在一些不合适的包中调用代码.
制作调度表可能更好.关于Mark Jason Dominus的高阶Perl中有一整章,您可以在他的网站上免费下载.
它基本上意味着您将所有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}->();
}
Run Code Online (Sandbox Code Playgroud)
这输出:
foobarbaz
wrong_entry is not allowed at /home/code/scratch.pl line 1494.
Run Code Online (Sandbox Code Playgroud)
您希望使用代码引用来实现.
foreach my $sub (@arr)
{
$sub->();
}
Run Code Online (Sandbox Code Playgroud)
其中@arr包含诸如的标量
my $rc = sub { print "Anonymous subroutine\n" };
Run Code Online (Sandbox Code Playgroud)
要么
sub func { print "Named sub\n" }
my $rc = \&func;
Run Code Online (Sandbox Code Playgroud)
您可以像处理任何其他标量一样操纵这些标量,以形成阵列.但是,将它们用作散列中的值更为常见和有用,从而创建调度表.