Re: List Variable becomes undefined inexplicably



On Sep 19, 8:32 pm, mattbreedl...@xxxxxxxxx wrote:
Using Perl v5.8.4
This type of problem has plagued me over the years several times. Each
time I have had to rearrange the way that my PERL script was designed
to work around it.

At this point I think its a bug or something really strange.
I was able to reproduce it with the test script below.

The issue is that a global list variable that is built inside
subroutine A, iterated over in a foreach loop in subroutine B, is then
magically undefined after the foreach loop if the loop contains a
command pipe with a while loop.

According the laws of PERL that I am used to when you run the below
script you *should* get:
main_before-ITERATE_HOSTS -apple orange durian-
start_inside_ITERATE_HOSTS -apple orange durian-
end_inside_ITERATE_HOSTS -apple orange durian-
main_after-ITERATE_HOSTS -apple orange durian-

However instead you get
main_before-ITERATE_HOSTS -apple orange durian-
start_inside_ITERATE_HOSTS -apple orange durian-
end_inside_ITERATE_HOSTS - -
main_after-ITERATE_HOSTS - -

Any ideas?

Here is the test script:

#!perl

use strict;
use warnings;



my @SLAVE_HOSTS;

SETUP_HOSTS();
print "main_before-ITERATE_HOSTS -@SLAVE_HOSTS-\n";
ITERATE_HOSTS();
print "main_after-ITERATE_HOSTS -@SLAVE_HOSTS-\n";

sub SETUP_HOSTS {


Note that you will be forced to quote barewords when using strict:

push(@SLAVE_HOSTS, apple);
push(@SLAVE_HOSTS, orange);
push(@SLAVE_HOSTS, durian);

}

sub ITERATE_HOSTS {
print "start_inside_ITERATE_HOSTS -@SLAVE_HOSTS-\n";

Here is part of your problem - using the default variable ($_)
It would be better to define a new variable
foreach my $slave (@SLAVE_HOSTS)
foreach (@SLAVE_HOSTS) {
Useless use of quotes
my $REMOTE_HOST = $_;
$REMOTE_HOST="$_";

#open(CMD, "$SSH $REMOTE_HOST 'do some stuff'|");

Note that you are using $_ as the loop variable here.
This is not good, as $_ is one of the elements of @SLAVE_HOSTS (see
above foreach)
When you modify $_ you modify an element of @SLAVE_HOSTS - essentially
you are 'undef' ing the whole array since the 'OPEN' statement is
commented.

while(<CMD>) {
chomp;
Useless use of quotes
my $LINE = $_;
$LINE="$_";
Useless use of quotes also no need to backslash the equal sign
if ( "$LINE" =~ /service id\=/ ) {
print "blah\n";
}
}
close(CMD);
}
print "end_inside_ITERATE_HOSTS -@SLAVE_HOSTS-\n";

}

HTH, Ken

.



Relevant Pages