如何使用变量名[per]调用perl中的子例程

前端之家收集整理的这篇文章主要介绍了如何使用变量名[per]调用perl中的子例程前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
参见英文答案 > How can I elegantly call a Perl subroutine whose name is held in a variable?                                    12个
假设我有一个包含所有子程序名称的数组,我想逐个调用.

foreach $sub (@arr){
      print "Calling $sub\n";
       #---How to call $sub?----
       &$sub;  ## will not work
}

解决方法

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

哎呀.你不想这样做.模具示例并不是很糟糕,但是像这样你可以很容易地在一些不合适的包中调用代码.

制作一个dispatch table可能更好.有一整章关于Mark Jason Dominus的高阶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.

猜你在找的Perl相关文章