kiat has asked for the wisdom of the Perl Monks concerning the following question:

Hi monks,

I've a contrived regex below that triggers "Use of uninitialised value in concatenation ..." warning.

use strict; use warnings; use diagnostics; my $str = "6%var% after"; # $str = "%var% after"; <-- warning is triggered $str =~ s/(\d)?%var%(.*)/$1REPLACED$2/; print "$str\n"
When both $1 and $2 are initialised (i.e. $1 matched to the digit 6 and $2 to the word after, no warning is triggered. But with the 6 gone, $1 becomes uninitialised and so the "Use of uninitialised value in..." warning is triggered.

How do I fix that?

Thanks in anticipation :)

Replies are listed 'Best First'.
Re: Regex triggering uninitialised values
by ikegami (Patriarch) on Nov 19, 2004 at 17:39 UTC

    Make the \d optional, not the capture:

    use strict; use warnings; my $str; #$str = "6%var% after"; $str = "%var% after"; # <-- warning is triggered $str =~ s/(\d?)%var%(.*)/$1REPLACED$2/; # <-- moved the '?' print "$str\n"

    By the way, I don't get the warning under Active Perl 5.6.1, but I did with perl v5.8.0 built for i386-freebsd

      Thanks, ikegami!

      How will the regex change if I need to match more than one digit before %var%? Just can't think of anything at the moment...

      Edited: Sorry, just discovered that moving the ? solves the problem.

      #$str =~ s/(\d+?)%var%(.*)/$1REPLACED$2/;</strikeout> As pointed out by Eimi Metamorphoumai $str =~ s/(\d*)%var%(.*)/$1REPLACED$2/;</strikeout>
        Watch out! '+?' isn't the same as '*' in a regexp. If you want zero or more, you want '*'. '+?' will only match if there is one or more, but will match non-greedily (that is, as few characters as possible).
Re: Regex triggering uninitialised values
by jimbojones (Friar) on Nov 19, 2004 at 17:36 UTC
    The following works for me:

    $str =~ s/(\d?)%var%(.*)/$1REPLACED$2/;
      Thanks, jimbojones!

      What if I need to match more than one digit before %var%?

        Then you'd have
        $str =~ s/(\d*)%var%(.*)/$1REPLACED$2/;
        Although, unless you're going to use $1 and/or $2 later, there's no reason to have them at all.
        $str =~ s/%var%/REPLACED/;
        (\d*)
Re: Regex triggering uninitialised values
by Kyoichi (Novice) on Nov 20, 2004 at 20:02 UTC
    Remember that you always have * and +.

    You need the use of * when you want to find 0 or more elements of the pattern ( say.. \d in your example ) and + if you want to find 1 or more elements of your pattern.

    So in your program, you're trying to find a \d everytime, so.. if you have \d*, you're telling perl that your regexp might find 0 or more numbers.

    Greetings
    -- Kyoichi