"Jerome Abela" <> wrote:
> Hi there,
>
> The following code comes directly from perlre(1), except it's inside a
> sub:
>
> animals();
> animals();
> sub animals {
> my ($color, $animal);
> $_ = "The brown fox jumps over the lazy dog";
> /the (\S+)(?{ $color = $^N }) (\S+)(?{ $animal = $^N })/i;
> print "color = $color, animal = $animal\n";
> }
>
> But its output is surprizing (at least with v5.8.5 and v5.8.7):
>
> color = brown, animal = fox
> color = , animal =
>
> Everything works if I don't declare lexical variables, so it may be
> related to some kind of scoping from inside the (?{}). But I can't find
> any reasonable explanation for this behavior.
The regex gloms onto the $color and $animal which are in scope the first
time the regex is encountered, and doesn't update them. The second time
animals is called, a different $color and $animal are created, but the
regex is still using the old ones.
It appears to be just like as if you did:
animals();
animals();
sub animals {
my ($color, $animal);
sub foo {
$color="brown";
$animal="fox";
};
foo();
print "color = $color, animal = $animal\n";
}
Only this generates a 'Variable "$color" will not stay shared' warning
while the regex does not generate warnings.
> I need help from more knowledgeable people: how can I write more robust
> code to be used from (?{}) expressions ?
Considering the "highly experimental" disclaimer, I would suggest you can't
write robust code to be used thus. Ignoring that, use a package variable.
>
> Or, as an alternative, how can I store data matched inside nested
> groups ?
I've never had problems doing that with plain old regular expressions.
> My real original code is more like:
> m/special\((?:before(group)after(?{save it, using $^N}))*\)/
> where the {save using $^N} part only works once because of the bug
> above.
How about something like:
my ($thing) = m/special\(((?:beforegroupafter)*)\)/ or die;
my (@data) = $thing=~/before(group)after/g;
Xho
--
--------------------
http://NewsReader.Com/ --------------------
Usenet Newsgroup Service $9.95/Month 30GB