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

Jas*_*nds 0 perl parameter-passing 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";
    }
}
Run Code Online (Sandbox Code Playgroud)

我收到输出有以下错误

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.
Run Code Online (Sandbox Code Playgroud)

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

sim*_*que 5

你的子程序的参数不在$_.它在阵列中@_,你需要把它拿出来.

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

或者作为列表分配

sub analyze_name {
    my ($name) = @_;
    ....
}
Run Code Online (Sandbox Code Playgroud)

或者,如果您想@_直接操作阵列

sub analyze_name {
    if ($_[0] =~ m/.../) { ... }
}
Run Code Online (Sandbox Code Playgroud)

现在我们正在访问数组中的第一个元素@_.Perl中变量名称前面的符号(称为sigil)随着该表达式返回的值的类型而变化.所以对于数组来说@_,但是当你访问一个元素时,它变成$_[0]因为里面的值是标量,这意味着它只是一个值.这与$_标量变量不同.同样的事情是关于真@array,$array[4]并且标量变量$array(这是一个严重的选择的名称).

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


$name在上面的代码是词法到该子程序.这意味着它只存在于那里,每次你调用那个sub,你就会得到一个新的$name.调用它时传入的变量的变量名称无关紧要.

analyze_name($foo);
analyze_name($bar);
analyze_name('foobar');
Run Code Online (Sandbox Code Playgroud)

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


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