Once in awhile Perl still surprises me.
This code is obviously broken:
my ($left, $right) = qw(abc def); print "$left_$right\n";
The problem is that interpolation causes Perl to want to print a variable $left_ and $right, but we declared $left and $right. There are several ways to fix this, two of which are:
print "$left\_$right\n"; print "${left}$right\n";
...and of course you could just use the concatenation operator, but then I wouldn't have anything to puzzle over.
But observe the following:
my $string = "abcd"; if ($string =~ m/(ab)(cd)/) { print "$1_$2\n"; }
The output is ab_cd. So in this case Perl automatically treated that interpolation as "${1}_$2\n" without me telling it to do so. I've looked over The Gory details of parsing quoted constructs and haven't found an explanation. I assume that in the case of numbered regex variables, Perl decides that if the variable starts with a numeric digit, the identifier must end when there are no more numeric digits. Is this behavior reliable? Is it documented? Is it likely to ever change?
I'm asking because I found it in a code review and was sure it was broken until we talked it over and tested to verify the behavior was to parse "$1_$2\n" as $1 . '_' . $2 . "\n" even though we would prefer to disambiguate using \ or ${n}.
Update: I do see in perldata: Identifier-parsing:
Meanwhile, special identifiers don't follow the above rules; For the most part, all of the identifiers in this category have a special meaning given by Perl. Because they have special parsing rules, these generally can't be fully-qualified. They come in six forms (but don't use forms 5 and 6):
- A sigil, followed solely by digits matching \p{POSIX_Digit}, like $0, $1, or $10000.
I don't know that this is worded quite right, because $1_ could be construed as NOT being an identifier consisting solely of digits. But it's the closest thing I can find to an explanation. But I'll take that as answering my own question: Yes, it's intentional and documented behavior.
Dave
In reply to How Perl decides where a variable ends and text starts: Match variables in string interpolation by davido
| For: | Use: | ||
| & | & | ||
| < | < | ||
| > | > | ||
| [ | [ | ||
| ] | ] |