[sf-perl] A bit of an eye opener with capture variables
David Alban
extasia at extasia.org
Thu Aug 3 13:11:24 PDT 2006
I'm reading Perl Best Practices and came across (p.253):
Pattern matches that fail never assign anything to $1, $2, etc., NOR
DO THEY LEAVE THOSE VARIABLES UNDEFINED.
[emphasis mine]
I've always thought that anything that didn't get matched was made to
be undef. I was very surprised to learn otherwise:
#!/usr/bin/perl
use warnings;
use strict;
my $strings = [
"d e f",
"b c",
"a",
];
for my $s ( @$strings ) {
print qq{'$s'\n};
$s =~ m{ \A \s* ( \S+ ) \s* ( \S+ ) \s* ( \S+ ) }xms;
my ( $a, $b, $c ) = ( $1, $2, $3 );
print " a => ", defined $a ? "<$a>" : "UNDEF", "\n";
print " b => ", defined $b ? "<$b>" : "UNDEF", "\n";
print " c => ", defined $c ? "<$c>" : "UNDEF", "\n";
} # for
This prints:
'd e f'
a => <d>
b => <e>
c => <f>
'b c'
a => <d>
b => <e>
c => UNDEF
'a'
a => <d>
b => <e>
c => UNDEF
Yikes!
The book goes on to explain this by saying that if a match fails, a
capture variable "may have been set by some earlier successful match
in the same scope".
So I tried changing the scope in which the match is done:
for my $s ( @$strings ) {
print "'$s'\n";
my ( $a, $b, $c );
do {
$s =~ m{ \A \s* ( \S+ ) \s* ( \S+ ) \s* ( \S+ ) }xms;
( $a, $b, $c ) = ( $1, $2, $3 );
};
print " a => ", defined $a ? "<$a>" : "UNDEF", "\n";
print " b => ", defined $b ? "<$b>" : "UNDEF", "\n";
print " c => ", defined $c ? "<$c>" : "UNDEF", "\n";
} # for
and got the results I had previously (erroneously) expected:
'd e f'
a => <d>
b => <e>
c => <f>
'b c'
a => UNDEF
b => UNDEF
c => UNDEF
'a'
a => UNDEF
b => UNDEF
c => UNDEF
Like I say, a bit of an eye opener.
David
--
Live in a world of your own, but always welcome visitors.
More information about the SanFrancisco-pm
mailing list