in reply to Why are elements of my array getting deleted?

This is probably a long shot, look at the code below. In it, the $_ variables are apparently tripping over each other.
#!/usr/local/perl510/bin/perl use strict; use warnings; use Data::Dumper; use IPC::Open3; my @plist = ( '/usr/bin/cat /etc/motd' ); sub ccmexec_nodie { my $command = $_[0]; my ($mystdin,$mystdout,$mystderr); my $pid = open3($mystdin,$mystdout,$mystderr,$command); my $myresult = ""; while(<$mystdout>){ $myresult = "$myresult$_"; } return $myresult; } print 'Before: ', Dumper \@plist; foreach ( @plist ) { print Dumper ccmexec_nodie $_; } print 'After: ', Dumper \@plist;
and the output it generates:
Before: $VAR1 = [ '/usr/bin/cat /etc/motd' ]; $VAR1 = 'Sun Microsystems Inc. SunOS 5.10 Generic January 2005 '; After: $VAR1 = [ undef ];
Now, this does NOT duplicate your problem! But, maybe you are running into something similar? Or assigning values to aliases like @_ and the values it contains (the $_[$index] variables). Or modifying @plist from within a for/foreach loop? I get the sense you are tripping over something along those lines.

In that light, I would suggest you eliminate all use of default variables like $_, make sure you are always using a copy of a variable, etc. and see if that changes anything. Something like:

#!/usr/local/perl510/bin/perl use strict; use warnings; use Data::Dumper; use IPC::Open3; my @plist = ( '/usr/bin/cat /etc/motd' ); sub ccmexec_nodie { my( $command )= @_; my ($mystdin,$mystdout,$mystderr); my $pid = open3($mystdin,$mystdout,$mystderr,$command); my $myresult = ""; while(my $in=<$mystdout>){ $myresult .= $in; } return $myresult; } print 'Before: ', Dumper \@plist; foreach my $cmd ( @plist ) { print Dumper ccmexec_nodie $cmd; } print 'After: ', Dumper \@plist;
Good luck!!

Elda Taluta; Sarks Sark; Ark Arks
My deviantART gallery

Replies are listed 'Best First'.
Re^2: Why are elements of my array getting deleted?
by iKnowNothing (Scribe) on Apr 19, 2012 at 00:51 UTC
    Thanks for the advice, your were on the right track. I was iterating over @plist in a foreach loop, as shown in the script example I posted above. There's definitely something funny going on with the $_ variable in that loop. I was able to get a workaround going, shown below, by replacing the foreach loop with a for loop. In my larger script, I simply index into @plist when necessary using $idx.
    use strict; use IPC::Open3; my @plist = ("ABC","DEF","GHI"); print "plist Before ccmexec:\n============\n",join("\n",@plist),"\n=== +=========\n\n"; my $ccmexecResult; my $idx = 0; for ($idx = 0; $idx <= $#plist;$idx++){ $ccmexecResult = ccmexec_nodie("echo HelloWorld"); print "ccmexec returned: $ccmexecResult\n"; print "plist After ccmexec:\n============\n",join("\n",@plist),"\n +============\n\n"; } sub ccmexec_nodie { my $command = $_[0]; my ($mystdin,$mystdout,$mystderr); my $pid = open3($mystdin,$mystdout,$mystderr,$command); my $myresult = ""; while(<$mystdout>){ $myresult = "$myresult$_"; } return $myresult; }

      ARGH, no, don't do that! Actually by now you've probably already seen my earlier reply. Argel was exactly right and the suggested fix of using an explicit variable in place of the default variable is a much better solution than resorting to a C style for loop.

      As an aside for and foreach are aliases in Perl. It is the syntax that distinguishes between the Perlish iterating over a list behaviour and the Cish for loop behaviour. Personally I use for in both cases because I'm lazy and can't be bothered typing the superfluous "each".

      The important lesson to learn from this is that the special variables are effectively globals and may change without notice, especially during the processing of a called subroutine. The default variable is most prone to this issue and should be avoided where possible in any non-trivial script.

      True laziness is hard work