in reply to Regex capture consumed by non-capturing match

We tell the children and we tell the children: use strict; use warnings;. In this case turning on warnings generates a whole bunch of

Use of uninitialized value in concatenation (.) or string at noname1.p +l line 23.

warnings. A clue perhaps? Indeed, an unsubtle clue! A hit you about the ears and do something clue. First thing to notice is that all the warnings are in trim_end, so remove trim_start and try again - same result. Ok, remove some cruft and the code looks like:

use strict; use warnings; my $test = 'abc , def'; $test =~ /([\s\w]+),([\s\w]+)/; for ($1, $2) { my $string = $_; $string =~ s/\s+\z//ms; print "$string\n"; }

and generates (omitting the warnings):

abc

Now look at what the code does. It performs a regular expression match setting $1 and $2. It then (in the loop) performs two more matches where the first fails and the second sees an undefined value. At this point it is worth noting from perlre that:

The numbered match variables ($1, $2, $3, etc.) and the related punctuation set ($+, $&, $`, $', and $^N) are all dynamically scoped until the end of the enclosing block or until the next successful match, whichever comes first.

but the first match in the loop is successful so $2 goes out of scope - becomes undefined. Capeesh?

Remember: use those strictures.


DWIM is Perl's answer to Gödel

Replies are listed 'Best First'.
Re^2: Regex capture consumed by non-capturing match
by erroneousBollock (Curate) on Jul 20, 2007 at 00:29 UTC
    I always prefer the form:

    my ($foo, $bar) = ($test =~ /(capt-pat-1)...(capt-pat-2)/);

    Doesn't get clobbered and is quite readable I think.

    -David.

      Yes, except that it is quite hard to write an if that checks if the match succeeded at all. I omitted this in the example, but in the real code this was the case:
      if ($string =~ /re/) { my ($a, $b, $c) = trim_func ($1, $2, $3); }

        Not so.

        if (my @matches = $string =~ /re/) { my ($a, $b, $c) = trim_func(@matches); }
Re^2: Regex capture consumed by non-capturing match
by ribasushi (Pilgrim) on Jul 20, 2007 at 16:00 UTC
    The children have been using strictures since day one. They were omitted from the example to keep it as small as possible. And besides they do not yield any information except what I already know - matches get undefined. So Teacher, leave those kids alone, thank you very much.
    As far as the fine perlre I misread it as in until the next successful capturing match, which does not seem to be the case as it was pointed out.

      We are pleased that the children are taking note of their lessons. ;)

      I assumed that you were not using strictures because you didn't mention the warning and "uninitialized value" warnings are not subtle. I see now that you meant to imply that the mechanism of the bug was subtle, rather than that the effects were subtle or the location of the faulty code was difficult to determine. My appologies for the misunderstanding.

      Note that we only know what you tell us. We didn't know from your node what the problem was - you didn't even present the output generated, nor the output you expected, let alone that you knew that the issue was an uninitialized value.


      DWIM is Perl's answer to Gödel