我正在将一个标量变量传递给子程序,在该子程序中我想测试参数是否与正则表达式匹配:
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>
变量上重用此子例程。如何初始化$_
?
答案 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";
}
}