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

I know why this is happening, however i can't for the life of me figure out how to prevent it.

I have a template file that contains items, like the following

<xml> <file>$rec->{filename}</filename> <ipv4>$rec->{IPAdress}</filename> <something>$foo</something> </xml>

On this file I do the following operation, in order to expand those varaible and hashrefs

for my $line (@template){ $line =~ s/(\$\w+->{\w+})/$1/eeg; $line =~ s/(\$\w+)/$1/eeg; $text .= $line; }

This technically works, however whenever $1 expands to a NULL value in the hashref (pulled from mysql). It errs with Use of uninitialized value in substitution iterator. I've tried a few things to get around it, neither worked, but i'm also unsure if either are techncially legal syntax. Those attempts are as follows

for my $line (@cfile){ $line =~ s/(\$\w+->{\w+})/$1||''/eeg; $line =~ s/(\$\w+)/$1||''/eeg; $text .= $line; }

as well as

for my $line (@cfile){ $line =~ s/(\$\w+->{\w+})/defined $1 ? $1 : ''/eeg; $line =~ s/(\$\w+)/defined $1 ? $1 : ''/eeg; $text .= $line; }

I've seen one example in the Monastery, but it didn't resolve the issue. Any insight would be greatly appreciated.

Replies are listed 'Best First'.
Re: Use of uninitialized value in substitution iterator in variable expansion
by Roy Johnson (Monsignor) on Apr 07, 2005 at 16:21 UTC
    Because you're executing twice (/eeg), you need to delay your defined test past the first time you expand $1:
    $line =~ s/(\$\w+)/"defined $1 ? $1 : ''"/eeg;
    should work. The first e will expand it to a statement, and the second will evaluate the statement.

    Caution: Contents may have been coded under pressure.
      or
      $line =~ s/(\$\w+->{\w+})/"$1 or ''"/eeg; # or $line =~ s/(\$\w+->{\w+})/eval "$1" or ''/eg; # or my favorite $line =~ s/(\$\w+->{\w+})/eval "$1" or print(STDERR "$1 is not defined\n"), ''/eg;
      -- gam3
      A picture is worth a thousand words, but takes 200K.

      This gives me the same warning. I thought it should work as well, though i wrote it like this with and without parans around the defined statement as mentioned above. Curious

      for my $line (@cfile){ $line =~ s/(\$\w+->{\w+})/defined $1 ? $1 : ''/eeg; $line =~ s/(\$\w+)/defined $1 ? $1 : ''/eeg; $text .= $line; }
        Quotation marks. I was suggesting you use quotation marks.
        #!perl use strict; use warnings; my $foo = undef; # No warning my $line = 'substitute for $foo in here'; $line =~ s/(\$\w+)/"defined $1 ? $1 : ''"/eeg; print $line, "\n"; # Warning $line = 'substitute for $foo in here'; $line =~ s/(\$\w+)/defined $1 ? $1 : ''/eeg; print $line, "\n";

        Caution: Contents may have been coded under pressure.
Re: Use of uninitialized value in substitution iterator in variable expansion
by Mutant (Priest) on Apr 07, 2005 at 15:55 UTC
    Use of uninitialized value is a warning. To disable it within a given scope use:
    no warnings 'uninitialised';
    If you're doing templating stuff, you may want to look into one of the many many (many!) templating modules on CPAN (eg. Text::Template). Chances are, there's one that does something you need, so it may be unneccsary to roll your own.

      I'm painfully aware of all the available templating systems on CPAN. However, You're looking at the complete extent of my use, and I didn't think I'd need to use an entire Template system in order to expand a few vars.

      While i could turn off warnings, I thought it best to first see if there was a "proper" way to resolve the warning from being printed. Should I assume that the only way around this type of warning is to disable it in some fashion? That may be entirely possible, but that's all i wanted to find out.

      thanks for the tip on disableing just that type of warning

Re: Use of uninitialized value in substitution iterator in variable expansion
by davido (Cardinal) on Apr 07, 2005 at 15:46 UTC

    If I recall, "Use of initialized value" messages are warnings, not fatal errors. So to silence it you would either trap the warning with a signal handler, or turn off warnings for that step. ...or maybe check for existance of a key before checking its definedness.


    Dave

Re: Use of uninitialized value in substitution iterator in variable expansion
by holli (Abbot) on Apr 07, 2005 at 15:50 UTC
    As a first countermeasure you can simply put a "no warnings" into your loop.
    for my $line (@template){ no warnings; $line =~ s/(\$\w+->{\w+})/$1/eeg; $line =~ s/(\$\w+)/$1/eeg; $text .= $line; }


    holli, /regexed monk/
Re: Use of uninitialized value in substitution iterator in variable expansion
by Roy Johnson (Monsignor) on Apr 07, 2005 at 16:51 UTC
    Unless you're worried that $line might include things that could be interpolated and shouldn't be, you could just evaluate the whole $line in double quotes:
    no warnings 'uninitialized'; $line = eval qq{"$line"};
    Update: Probably the most hazardous thing might be any double-quotes that were in the file. If the lines will be free of unbalanced braces, this would be better:
    $line = eval "qq{$line}";

    Caution: Contents may have been coded under pressure.