If I comment out the Dumper($cmd_string)
then the while
loop is never taken.
What side effects does Dumper() have on $cmd_string?
Here is what $cmd_string is before the sub call:
VAR1 = {
'The Java Runtime Library' => {
'apt-get install -y' => 'sun-java6-jre'
}
};
sub installPackages
{
my $cmd_string = shift;
my %rc_hash;
my $rc;
Dumper($cmd_string);
for my $desc (keys %{$cmd_string})
{
while (my ($cmd, $arg) = each %{$cmd_string->{$desc}})
{
print "system($cmd $arg)\n";
$rc = system("$cmd $arg");
if ($rc)
{
$rc_hash{$desc}{$cmd} = '';
}
}
}
return \%rc_hash;
}
If I run the Perl debugger without the Dumper() and use the x command on $cmd_string then it works, but if I just step through the code it does not work.
This is after only stepping though the code at the end of the sub
DB<3> x $cmd_string
0 HASH(0x2769550)
'' => HASH(0x2769880)
empty hash
'The Java Runtime Library' => HASH(0x25cc2a0)
'apt-get install -y' => 'sun-java6-jre'
DB<4> x $cmd_string->{$desc}
0 HASH(0x2769880)
empty hash
Now, if I x $cmd_string before the for loop I get this at the end of the sub
main::installPackages(msi.pl:1979): return \%rc_hash;
DB<3&开发者_高级运维gt; x $cmd_string
0 HASH(0x1125490)
'The Java Runtime Library' => HASH(0xf852a0)
'apt-get install -y' => 'sun-java6-jre'
The each
iterator over hashes uses a hidden per hash variable to keep track of where it is in the hash. My guess is that the code used to generate the $cmd_string
hash also uses each
but is not iterating to completion.
To reset the each
iterator, place keys %{$cmd_string->{$desc}};
before your while loop. Calling keys
in void context is the standard way of resetting the hash iterator.
Alternatively, just use for my $cmd (keys %{$cmd_string->{$desc}}) {
and then create the $arg
variable inside the loop.
The reason why using Dumper()
fixes the problem is that Dumper most likely calls keys
on the hash, thereby resetting the iterator.
精彩评论