在 Perl 中,如何将变量作为参数传递给子例程?

In Perl, how can I pass a variable as an argument to a subroutine?

我正在将标量变量传递给子例程,我想在其中测试参数是否与正则表达式匹配:

use strict;
use warnings;

use Data::Dumper;

print "Please enter your first name followed by your last name. For example: John Smith.\n";

chomp(my $name = <STDIN>);

&analyze_name($name);

sub analyze_name {
    if ($_ =~ /^\w+\s+\w+$/) {
            print "You entered $_.";
                    } else {
            print "Incorrect convention";
    }
}

我收到以下错误的输出

Please enter your first name followed by your last name. For example: John Smith.
firstname lastname
Incorrect convention
Use of uninitialized value $_ in pattern match (m//) at /home/jhusbands/scripts/examples/test.pl line 13, <STDIN> line 1.

我的想法是它会将 $name 传递给 "magic variable" $_。我需要在多个 <STDIN> 变量上重用这个子例程。如何初始化 $_?

您的子例程的参数不在 $_ 中。在数组@_里面,需要把它取出来

sub analyze_name {
    my $name = shift; # implicitly shifts @_
    if ($name =~ m/.../) { ... }
}

或者作为列表分配

sub analyze_name {
    my ($name) = @_;
    ....
}

或者,如果你想直接对@_数组进行操作

sub analyze_name {
    if ($_[0] =~ m/.../) { ... }
}

现在我们正在访问数组 @_ 中的第一个元素。在 Perl 中,变量名前面的符号(称为 sigil)随该表达式 returns 的值类型而变化。所以对于数组来说它是@_,但是当你访问一个元素时,它变成了$_[0],因为里面的值是标量,这意味着它只有一个值。这与 $_ 不同,它是一个标量变量。 @array$array[4] 和标量变量 $array(这是一个错误的名称)也是如此。

在大多数情况下,您想要执行 shift 或列表分配。如果您有两个或三个参数,列表通常更容易阅读。如果有很多参数,每行一个是有意义的。直接在 @_ 上操作通常只有在速度是个问题时才有意义,因为你的子程序在你的程序中被调用了数百万次。 我的建议是代码可读性高于简洁性,并使用正确命名的参数


上面代码中的$name是那个子程序的词法。这意味着它只存在于那里,每次你调用那个 sub 时,你都会得到一个新的 $name。调用时传入的变量的变量名无所谓

analyze_name($foo);
analyze_name($bar);
analyze_name('foobar');

所有这些都将值传递给 sub。 sub 不关心变量名。在 sub 中,它总是 $name。在 sub 之外,$name 不存在。


请注意,您不应在 Perl 中使用 & 调用 subs。这曾经是大约 20 年前 Perl 4 中的语法。在 Perl 5 中,这个 &foo() 有一个你可能不想要的特殊含义。删除 &,然后查找 子程序原型 如果您想了解更多相关信息。

如果您只想让您的代码正常工作,您需要更改:

if ($_ =~ /^\w+\s+\w+$/) {

if ($_[0] =~ /^\w+\s+\w+$/) {

perl 一起安装的 Perl 文档 perldoc perlsub 说:

Any arguments passed in show up in the array @_ . ... if you called a function with two arguments, those would be stored in $_[0] and $_[1] . The array @_ is a local array, but its elements are aliases for the actual scalar parameters.

相反,我建议您将参数存储到变量中,并避免使用“&”调用子例程,正如 simbabque 在他的回答中所说,所以:

use strict;
use warnings;

use Data::Dumper;

print "Please enter your first name followed by your last name. For example: John Smith.\n";

chomp(my $name = <STDIN>);

analyze_name($name);

sub analyze_name {
  my ( $name ) = @_;

    if ($name =~ /^\w+\s+\w+$/) {
            print "You entered $name.";
                    } else {
            print "Incorrect convention";
    }
}