in reply to Problem with regexp or saved match variable.

The reason this, and many other variables are persistent, is that they're "global special variables", which is to say, Main::variable_name has some magic to it (in this case, Main::$3 is the third captured match). The upshot is, once $3 gets set by a match, it can't go away by going out of scope (Ignore that, it was wrong. Match variables are implicitly dynamically scoped for extra magic, as ig points out in the reply below.) perlvar could provide some further enlightenment on the subject (or might bury you in details). As the other answers have said, you need to test that the match succeeded before you use the result.
  • Comment on Re: Problem with regexp or saved match variable.

Replies are listed 'Best First'.
Re^2: Problem with regexp or saved match variable.
by ig (Vicar) on Aug 27, 2009 at 08:18 UTC

    I'm not sure, but it seems otherwise to me. Consider the following example:

    my $_ = '1'; /(.)/; print "before: \$1 = $1\n"; for (2..4) { print "\$_ = $_\n"; print "first: \$1 = $1\n"; /(3)/; print "second: \$1 = $1\n"; } continue {} print "after: \$1 = $1\n";

    Which produces

    before: $1 = 1 $_ = 2 first: $1 = 1 second: $1 = 1 $_ = 3 first: $1 = 1 second: $1 = 3 $_ = 4 first: $1 = 1 second: $1 = 1 after: $1 = 1

    At least it is not the case that once a capture variable is set it can't go away by going out of scope. Not only does $1 of the inner scope go away after the loop is completed, but the previous value of the outer scope's $1 remains, unaltered by $1 having been set in the inner scope. And the $1 of the inner scope doesn't even persist from one iteration of the loop to the next. While this effect could be achieved by localization of a global variable, perlre says explicitly that the numbered match variables are dynamically scoped. And my understanding of dynamically scoped is that they are lexical variables, not localized global variables. Of course, I could be was wrong and confused dynamic and lexical scoping. , as could the documentation. I haven't looked at the implementation.

      Maybe I'm misunderstanding what you're trying to say in your last paragraph, but localizing a variable *is* dynamic scoping. my is lexical scoping.

      Note that if you use while things get hairier:

      my $i=1; $i=~/(.)/; while ($i++<=4) { print "\$i = $i\n"; print "first: \$1 = $1\n"; $i=~/(3)/; print "second: \$1 = $1\n"; } print "after: \$1 = $1\n";
      Gives
      $i = 2 first: $1 = 1 second: $1 = 1 $i = 3 first: $1 = 1 second: $1 = 3 $i = 4 first: $1 = 3 second: $1 = 3 after: $1 = 1

      Clearly there's some dynamic scoping going on, which is likely to save a lot of people from small mistakes. But in my example, it's all one block of code, so the inner result persists. I'm pretty sure it's easy to come up with lots of real-world examples of iterating with while and a capturing regex...so, caveat programmer.

        Thanks for spotting my error. I had confused dynamic and lexical. I'll go re-read Variables and Scoping now.

        As with the foreach loop, if you add a continue block (even an empty one) the behavior through the main loop block changes.

        my $i=1; $i=~/(.)/; while ($i++<=4) { print "\$i = $i\n"; print "first: \$1 = $1\n"; $i=~/(3)/; print "second: \$1 = $1\n"; }continue{} print "after: \$1 = $1\n";

        gives

        $i = 2 first: $1 = 1 second: $1 = 1 $i = 3 first: $1 = 1 second: $1 = 3 $i = 4 first: $1 = 1 second: $1 = 1 $i = 5 first: $1 = 1 second: $1 = 1 after: $1 = 1

        I find the behavior without the continue block quite surprising but it might be intentional and a beneficial "feature" in some cases. If it's an intentional feature, it should be documented but there is no mention of this behavior in the obvious places. Thus my bug report.

        At least the behavior is consistent between while and for loops.