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

Use of uninitialized value in concatenation (.) or string Hi, The piece of code works fine but gives a warning message.
#!/usr/bin/perl -w use strict; my %words = map { $_ => 1 } qw($Word $name); my $line = '$Word $'; $line =~ s/(\$(\w+)?)/exists $words{$1} ? $1 : "dollar$2"/eg; print "$line\n\n";
How to initialize the $2. I have to check in array, whether the regular expression matches and if it does not match change the “$” to “dollar”. But if the single character “$” it gives a warning message as “$2” is empty

Replies are listed 'Best First'.
Re: Use of uninitialized value in concatenation
by GrandFather (Saint) on Jun 11, 2009 at 05:35 UTC

    The minimum the regex can match is a $ because the second capture is optional. If there are no \w characters following a $ character then the second capture will be undef and you get the warning. There are two ways you can fix it depending on the desired result. Using

    (\$(\w+))

    prints '$Word $' for the sample line, and

    (\$(\w*))

    prints '$Word dollar'.


    True laziness is hard work
      For the example like this
      #!/usr/bin/perl -w use strict; my %words = map { $_ => 1 } qw($Word $name); my $line = '$Word $ $1'; $line =~ s/(\$(\w+)?)/exists $words{$1} ? $1 : "dollar$2"/eg; print "$line\n\n";
      It gives a warning message
Re: Use of uninitialized value in concatenation
by AnomalousMonk (Archbishop) on Jun 11, 2009 at 05:35 UTC
    The regex expression  (\w+)? means "capture one or more word characters... or don't". This is the same as saying  (\w*): "capture zero or more word characters", and if zero characters are captured, you are left with an empty – but perfectly defined – string.
    >perl -wMstrict -le "my %words = map { $_ => 1 } qw($Word $name); my $line = '$Word $'; $line =~ s/(\$(\w*))/exists $words{$1} ? $1 : qq{dollar$2}/eg; print $line; " $Word dollar
Re: Use of uninitialized value in concatenation
by Utilitarian (Vicar) on Jun 11, 2009 at 05:35 UTC
    Your code will never assign a value to $2.
    If I understand correctly you want to change to $ to a literal "dollar" if the string after it is not a key of the hash.?
    $line =~ s/(\$)(\w+)?/$2 ne ""?(exists $words{$2} ? "$1$2" : "dollar$2 +"):"dollar"/eg;
Re: Use of uninitialized value in concatenation
by targetsmart (Curate) on Jun 11, 2009 at 05:34 UTC
    if i understand your problem right, this could be the solution.
    use strict; use warnings; my %words = map { $_ => 1 } qw($Word $name $test); my $line = '$Word $ $ $ $test'; $line =~ s/(\$\w*)/exists $words{$1} ? $1 : " dollar "/eg; print "$line\n\n";
    will produce
    $Word dollar dollar dollar $test

    UPDATE
    thanks AnomalousMonk, actually i misunderstood the problem :)
    this could do it

    $line =~ s/(\$(\w*))/exists $words{$1} ? $1 : "dollar$2"/eg;

    Vivek
    -- In accordance with the prarabdha of each, the One whose function it is to ordain makes each to act. What will not happen will never happen, whatever effort one may put forth. And what will happen will not fail to happen, however much one may seek to prevent it. This is certain. The part of wisdom therefore is to stay quiet.
      >perl -wMstrict -le "my %words = map { $_ => 1 } qw($Word $name); my $line = '$Word $ $foo'; $line =~ s/(\$\w*)/exists $words{$1} ? $1 : qq{ dollar }/eg; print $line; " $Word dollar dollar
      I think the OPer wants '$foo' to be replaced by 'dollarfoo'. And what's with the extra spaces?
        #!/usr/bin/perl -w use strict; my %words = map { $_ => 1 } qw($Word $name); my $line = '$Word $ $foo'; $line =~ s/(\$\w*)/exists $words{$1} ? $1 : qq{ dollar }/eg; print $line;
        For $foo it prints dollar and not dollarfoo. But still gets a warning message