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

As a sane person, I run my Perl programs with -w. So today I stumbled across an interesting problem:

# This works fine $a = "abc"; $a =~ s/^(?:a(\w))?(\w)$/$1:$2/; # works fine # This produces the warning # "Use of uninitialized value in concatenation (.) $b = "c"; $b =~ s/^(?:a(\w))?(\w)$/$1:$2/;

I do not mind $1 to be empty; in fact, I want it to be empty if ^a\w is not there. But I only want to put the second character in $1 if the first character is "a", so

$b =~ s/^a?(\w?)(\w)$/$1:$2/; # no warning here.

won't do. The $64,000 question is, can I accomplish this in one line and not produce a warning?

Replies are listed 'Best First'.
Re: Uninitialized $1 in s///
by mirod (Canon) on Jan 02, 2002 at 09:33 UTC

    This code does not generate a warning under 5.6.1, so an easy answer would be to upgrade your version of Perl.

    An other way is to use the /e option is the substitution:

    $b =~ s/^(?:a(\w))?(\w)$/defined $1? "$1:$2" : ":$2"/e; <>The /e option evals the right part of the s/// operator, so you can test whether $1 is defined or not.

      s///e is inefficient though; and this feels like a workaround more than a fix to me.

      Edit: on the other hand, it seems there really is no way to get around this on 5.6.0. The only thing I could come up with, though it seems slightly more efficient than s///e, is many times more kludgy:
      $b = $1 || "" . ":$2" if $b =~ /^(?:a(\w))?(\w)$/;
      (Which amounts to the same thing expressed in a different way..)
      Aha, so it's the interpreter's fault. /e is not as cute :)

      I can probably do something like

      $command = join(":", $command =~ /^(?:a(\w))?(\w)$/);

      but this requires an extra function call.

Re: Uninitialized $1 in s///
by blakem (Monsignor) on Jan 13, 2002 at 14:05 UTC
    I've been known to rant about that warning a time or two, so I'd suggest just turning it off. Since the override is lexically scoped, this won't affect other parts of your code....
    $b = "c"; { no warnings 'uninitialized'; # turn off bogus warning for this bl +ock $b =~ s/^(?:a(\w))?(\w)$/$1:$2/; # voilla, no warning!! }

    -Blake