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

时间:2017-06-14 15:22:38

标签: 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";
    }
}

我收到输出时出现以下错误

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传递给&#34;魔术变量&#34; $_。我需要在多个<STDIN>变量上重用此子例程。如何初始化$_

2 个答案:

答案 0 :(得分:5)

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

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

或者作为列表分配

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

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

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

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

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

上面代码中的$name lexical 到该子程序。这意味着它只存在于那里,每当你调用那个sub时,你就得到一个新的$name。您调用它时传入的变量的变量名称并不重要。

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

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

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

答案 1 :(得分:0)

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

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

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

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

  

传入的任何参数都显示在数组@_中。   ...    如果你打电话给   具有两个参数的函数,这些参数将存储在$_[0]$_[1]中   。数组@_是一个本地数组,但它的元素是   实际的标量参数。

相反使用它我建议你将参数存储到变量中,并避免使用“&amp;”调用子程序正如 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";
    }
}