I am working on patching the Zoidberg Perl shell to fix some errors that modern Perl versions throw when testing. Note, I am not the original author nor am I criticizing him. I came upon an interesting problem that I would like a little history on.
The code below takes an array of inputs and for each strips off and ending sigil. Then it stores that sigil in a variable, if it didn't find it store 0 instead. The code that was in the original file looked like test A and must have worked until and including perl v5.8 given cpantesters results. Anyway the problem is that if the s/// isn't inside an of an "if" test, upon looping the $1 variable persists with the last value. Here are my tests. I was wondering if people could explain why this happens and or/why it used to work, I think I understand what is happening.
#!/usr/bin/perl
use strict;
use warnings;
my @a = qw/n a$ b@ c/;
my @b = @a;
my @c = @a;
print "Test A -- Doesn't work (c !-> 0)\n";
for (@a) {
s/([\$\@\%])$//;
my $arg = $1 || 0;
print $_ . " -> " . $arg . "\n";
}
print "\nTes开发者_JAVA百科t B -- Works\n";
for (@b) {
my $arg;
if (s/([\$\@\%])$//) {;
$arg = $1;
}
$arg ||= 0;
print $_ . " -> " . $arg . "\n";
}
print "\nTest C -- Works, more clever\n";
for (@c) {
my $arg = s/([\$\@\%])$// ? $1 : 0;
print $_ . " -> " . $arg . "\n";
}
From perlre:
NOTE: Failed matches in Perl do not reset the match variables, which makes it easier to write code that tests for a series of more specific cases and remembers the best match.
But you're right, Test A did work like the other two in 5.8.9. I can't find anything in the 5.10.0 release notes that explains it, but there were numerous RE changes in 5.10, and one of them must have affected this. I don't think the 5.8 behavior was ever intended.
精彩评论