I am passing a scalar variable to subroutine in which I want to test if the argument matches a regex:
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";
}
}
I am getting output with the following error
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.
My thinking is it would pass $name
to the "magic variable" $_
. I need to reuse this subroutine on multiple <STDIN>
variables. How do I initialize $_
?
The argument to your subroutine is not in $_
. It's in the array @_
, and you need to get it out.
sub analyze_name {
my $name = shift; # implicitly shifts @_
if ($name =~ m/.../) { ... }
}
Or alternatively as a list assignment
sub analyze_name {
my ($name) = @_;
....
}
Or, if you wanted to operate on the @_
array directly
sub analyze_name {
if ($_[0] =~ m/.../) { ... }
}
Now we are accessing the first element in the array @_
. The sign in front of the variable name (called a sigil) in Perl changes with the type of value that that expression returns. So for the array it's @_
, but when you access an element, it becomes $_[0]
because the value inside is scalar, which means it is only one value. This is different from $_
, which is a scalar variable. The same thing is true about @array
, $array[4]
and the scalar variable $array
(which is a badly chosen name).
In most cases you want to do either the shift
or the list assignment. If you have two or three arguments, the list is often easier to read. If there are a lot of args, having them one per line makes sense. Operating on @_
directly usually only makes sense if speed is an issue because your sub is called millions of times in your program. My advice is to take readable code over brevity and go with properly named arguments.
The $name
in the above code is lexical to that subroutine. That means it exists only there, and every time you call that sub, you get a new $name
. The variable name of the variable you pass in when you call it doesn't matter.
analyze_name($foo);
analyze_name($bar);
analyze_name('foobar');
All of those pass a value to the sub. The sub does not care about the variable name. In the sub, it's always $name
. Outside of the sub, $name
does not exist.
Note that you should not call subs with &
in Perl. That used to be the syntax in Perl 4 about 20 years ago. In Perl 5 this &foo()
has a special meaning that you probably do not want. Drop the &
, and look for subroutine prototypes if you want to know more about that.