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

I am running a script that gives me the following output:

user@host1::perl: ./1.pl Are you sure you would like to delete all *.bak files that exist in: /dir/etc-test yes/no yes
No files were found
$VAR1 = {};
>>> Oper Sys: linux
>>> Platform: RedHat
>>> Hostname: host1

I am so far not able to figure out why the data is missing. This exact code was working and all I did to it was enclose it into a sub and add an if statement ($platform_in).

This script is getting quite long now so I am only adding the code for the call and the sub. If you want to see additional code I will post it all

my @nicdata = networkInfo($platform); sub networkInfo { my $platform_in = shift; my ($nics, %nic); if ($platform_in =~ /RedHat/) { $nics = qx |/sbin/ifconfig| or die("Can't get info from Linux +ifconfig: $!\n"); my @nics = split /(?<=\n)(?=\w)/, $nics; for (@nics) { my %nic; ($nic{device}) = $_ =~ /^(eth\d)\s/ or next; if (/\binet addr:([\d.]+)\s.+?:([\d.]+)\s.+?:([\d.]+)/) { $nic{ip} = $1; $nic{bcast} = $2; $nic{mask} = $3; #print "Device: $nic{device} has the IP Address of $ni +c{ip}\n\tMask: $nic{mask}\n\tBroadcast: $nic{bcast}\n"; } if (/^\s+ inet6 addr:\s*(\S+)/m) { $nic{ip6} = $1; #print "Device: $nic{device} also has IPv6 address of +$nic{ip6}\n"; } } } elsif ($platform_in =~ /SunOS/) { $nics = qx |/sbin/ifconfig -a| or die("Can't get info from Sol +aris ifconfig: $!\n"); my @nics = split /(?<=\n)(?=\w)/, $nics; for (@nics) { my %nic; ($nic{device}) = $_ =~ /^(fjgi\d)\s/ or next; if (/\binet addr:([\d.]+)\s.+?:([\d.]+)\s.+?:([\d.]+)/) { $nic{ip} = $1; $nic{bcast} = $2; $nic{mask} = $3; print "Device: $nic{device} has the IP Address of $nic +{ip}\n\tMask: $nic{mask}\n\tBroadcast: $nic{bcast}\n"; } if (/^\s+ inet6 addr:\s*(\S+)/m) { $nic{ip6} = $1; print "Device: $nic{device} also has IPv6 address of $ +nic{ip6}\n"; } } } # => ENABLE DEBUGGING MODE use Data::Dumper; print Dumper(\%nic); #return (\%nic); # Do all printing here.... # this statement needs work. # print "Device: $a\n\tIPv4: $b\n\tBcast: $c\n\tMask: $d\n\tIPv6: $e +\n"; }

Replies are listed 'Best First'.
Re: Data::Dumper is returning empty
by kennethk (Abbot) on Jan 19, 2010 at 17:47 UTC
    As you may have guessed, the reason Data::Dumper is returning empty is because you are feeding it an empty variable. The reason %nic is empty is because you are having scoping issues. You declare a hash %nic on line 5 of the posted code and that is what gets fed into your print statement on line 45. However, on lines 10 and 28 you have the statement my %nic;. This creates a new variable, scoped to each iteration of your for loops, that overrides the previous entry in the symbol table so long as it is in scope - see Private Variables via my(). The solution to your problem should be as simple as deleting lines 10 and 28.

    Update: See ikegami's response below, regarding creating a array of hashes to export your results. It is a scoping issue, but not quite what I initially thought.

      Good explanation, but the conclusion is backwards. Line 10 and 28 are correct; it's line 5 that's wrong. There are multiple nics, so there should be multiple hashes. The real problem is that the function pretends there's only one. It should be returning a list of nics (list of hashes).

      sub networkInfo { my @nics; my $platform = getPlatform(); if ($platform =~ /RedHat/) { my $ifconfig = qx|/sbin/ifconfig| or die("Can't get info from Linux ifconfig: $!\n"); for (split /(?<=\n)(?=\w)/, $ifconfig) { my %nic; ($nic{device}) = /^(eth\d)\s/ or next; if (/\binet addr:([\d.]+)\s.+?:([\d.]+)\s.+?:([\d.]+)/) { $nic{ip} = $1; $nic{bcast} = $2; $nic{mask} = $3; } if (/^\s+ inet6 addr:\s*(\S+)/m) { $nic{ip6} = $1; } push @nics, \%nic; } } elsif ($platform =~ /SunOS/) { my $ifconfig = qx|/sbin/ifconfig -a| or die("Can't get info from Solaris ifconfig: $!\n"); for (split /(?<=\n)(?=\w)/, $ifconfig) { my %nic; ($nic{device}) = /^(fjgi\d)\s/ or next; if (/\binet addr:([\d.]+)\s.+?:([\d.]+)\s.+?:([\d.]+)/) { $nic{ip} = $1; $nic{bcast} = $2; $nic{mask} = $3; } if (/^\s+ inet6 addr:\s*(\S+)/m) { $nic{ip6} = $1; } push @nics, \%nic; } } return @nics; } for my $nic (networkInfo()) { print(join( "\t", map $_//'[undef]', @{$nic}{qw( device ip ipv6 bcast mask )} ), "\n"); }

      Update: Cleaned up opening paragraph.
      Update: Second push discovered ability to turn invisible. Added anti-invisibility field to post so it's visible again.

        I am getting an error when I try to run this code. It says

        Search pattern not terminated at ./sec-test.pl line 166 (#1) (F) The lexer couldn't find the final delimiter of a // or m{} construct. Remember that bracketing delimiters count nesting level. Missing the leading $ from a variable $m may cause this error. Note that since Perl 5.9.0 a // can also be the defined-or construct, not just the empty search pattern. Therefore code written in Perl 5.9.0 or later that uses the // as the defined-or can be misparsed by pre-5.9.0 Perls as a non-terminated search pattern. Uncaught exception from user code: Search pattern not terminated at ./sec-test.pl line 166. at ./sec-test.pl line 166

        line 166 is the map $_//'[undef]', line

        Also how would I return to main so I could run the following code section, or code similar to what I have below?

        my %nicdata = networkInfo($platform); for (@nicdata) { print "Device: $nic{device} has the IP Address of $nic{ip}\n\tMask +: $nic{mask}\n\tBroadcast: $nic{bcast}\n"; print "Device: $nic{device} also has IPv6 address of $nic{ip6}\n"; }
Re: Data::Dumper is returning empty
by Corion (Patriarch) on Jan 19, 2010 at 17:45 UTC

    As likely steps, I would verify that $platform_in contains what you think it should. It looks as if you never modify %nic which is why Data::Dumper shows it as empty. Note also how none of your print statements appear in the output.

    This leads me back to some old IBM research I remember that every if statement needs an else branch, as I remember them finding a high likelyhood that an if without the corresponding else was an error. In your case, you should add a final else branch to your chain of if statements that check the operating systems, and in that else branch either die or at least output something that you don't know what to do with $platform_in.