SPUG:Use of (?{}) in a subroutine gives off weirdness with $^N

Chris Wilkes cwilkes-spug at ladro.com
Wed Jan 29 02:30:04 CST 2003


I thought I would try out the (?{}) construct to see how it works, and
for the most part it is working except when I put it in a subroutine.

The following code works:

-----------------------------------------------
  #!/usr/bin/perl -w
  use strict;
  my $amt;
  $_ = "you owe me 100";
  /
    \s+ # start of whitespace
      (\d+) (?{ $amt = $^N })
    \s*$ # anything afterwards
  /x;
  print "$amt,$_\n";
  $_ = "bank owes me 200";
  /
    \s+ # start of whitespace
      (\d+) (?{ $amt = $^N })
    \s*$ # anything afterwards
  /x;
  print "$amt,$_\n";
-----------------------------------------------

But if I do the (?{}) in a subroutine the $amt variable is lost the 2nd
time around, even though it should get the $^N value:

-----------------------------------------------
  #!/usr/bin/perl -w
  use strict;
  my ($line, $amt);
  
  $line = "you owe me 100";
  $amt = modline($line);
  print "$amt,$line\n";
  
  $line = "bank owes me 200";
  $amt = modline($line);
  print "$amt,$line\n";
  
  sub modline {
    my $tmpline = shift;
    my $tmpamt;
    $tmpline =~
       /
        \s+ # start of whitespace
          (\d+) (?{ $tmpamt = $^N ; print "found '$tmpamt'\n"; })
        \s*$ # anything afterwards
       /x;
    return $tmpamt;
  }
-----------------------------------------------


What gives?  I threw in the print statement in the sub to see if the
pattern is matching and it does.  You can take it out and look at the
$^R value after the regex and see that it contains the digit matched (if
you leave in the print $^R is set to 1, the return code of print).

Looking through the perlre perldoc I suspect it has something to do with
this:
  The code is properly scoped in the following sense: If the assertion
  is backtracked (compare the section on Backtracking), all changes
  introduced after localization are undone,
but what I can't understand is that if the match worked the first time
through, why not the second?

Am I using (${}) in a bad way?

Chris



More information about the spug-list mailing list