in reply to Again on "can't use string as hash as HASH ref while "strict refs" in use"

Hello guys,
first of all thank you very much for your help, much appreciated.
I tried to run the Dumper and got the following output:

$VAR1 = { 'cfg' => bless( { 'devicecount' => 2, 'sshpass' => '/home/cfgbackup/bin/sshpass' +, 'version' => '$Id: 1.3$', 'task' => { '1' => 'ip', '2' => 'name' }, 'default' => { 'passwd' => 'XXXX', 'KH' => '/tmp/known_hosts.1 +0823', 'destination' => '/home/cfg +backup/cfg', 'cryptpwd' => 'XXXXX', 'remotefile' => 'running-co +nfig', 'logdir' => '/home/cfgbacku +p/log', 'rcsdir' => '/home/cfgbacku +p/cfg/RCS', 'logfile' => '/home/cfgback +up/log/cfgbackup.log', 'username' => 'XXXXXX' }, 'device' => { 'ip' => '192.168.0.1', 'name' => 'switch' }, 'devices' => [ 'ip', 'name' ], 'bindir' => '/home/cfgbackup/bin' }, 'CFGBACKUP' ), 'devfail' => 2, 'devok' => 0, 'starttime' => 'Wed Aug 26 08:21:23 2015', 'task' => {} };

The error that I get when I run the script is:

Can't use string ("192.168.0.1") as a HASH ref while "strict refs" in +use at ./cfg_backup line 203.

The data for the devices are taken from a xml file that is read via XML::Simple.

Replies are listed 'Best First'.
Re^2: Again on "can't use string as hash as HASH ref while "strict refs" in use"
by Corion (Patriarch) on Aug 26, 2015 at 14:19 UTC

    Your data structure has no localfile entry, but you try to access it:

    my $CFG = $heap->{cfg}->{device}->{$name}->{localfile};

    What do you expect to happen here?

    The path through your data structure ends at 192.168.0.1, which is what Perl told you. There is no localfile below that. You need to go back and talk to the people writing the XML structure what should happen here. Also, using XML::Simple is often problematic, as it usually brings problem if a structure only repeats once or repeats multiple times.

Re^2: Again on "can't use string as hash as HASH ref while "strict refs" in use"
by stevieb (Canon) on Aug 26, 2015 at 14:27 UTC

    Ok, so when you do this:

    foreach my $name (@{ $heap->{cfg}->{devices} }) {

    ...you're actually looping over:

    devices => [ 'ip', 'name', ]

    array. In the next line, you're taking each one of those elements, say ip, and using it as the $name key in $heap->{cfg}->{device}->{$name} to get the value.

    However, the value of $heap->{cfg}->{device}->{ip} is an actual IP address. You then proceed to attempt to access the localfile key from it, but of course the IP address is a string, so there's nothing perl can do (with use strict;) which is a very good thing (trust me).

    With what I've seen so far, it doesn't look like you want to be doing any looping at all based on the structure you've got here... well, at least it looks like you don't want to loop over this specific structure.

    Also, localfile is not present in your data at all. It appears it might fit into the default hash, but can't tell at this point.

    You're going to have to post the entire script you're using in order to figure out at a higher level what's going on and is supposed to be going on.

    -stevieb

Re^2: Again on "can't use string as hash as HASH ref while "strict refs" in use"
by poj (Abbot) on Aug 26, 2015 at 15:31 UTC

    This demo shows how with XML simple your structure can change depending on how many devices you have in the xml.

    #!perl use strict; use warnings; use XML::Simple; use Data::Dump 'pp'; my @xml=(); # 2 devices $xml[0] = ' <xml> <cfg> <device name="switch1" ip="192.168.0.1" localfile="filename1"/> <device name="switch2" ip="192.168.0.2" localfile="filename2"/> </cfg> </xml>'; # 1 device $xml[1] = ' <xml> <cfg> <device name="switch1" ip="192.168.0.1" localfile="filename1"/> </cfg> </xml>'; # run for each xml for my $i (0..1){ my $heap = XMLin($xml[$i]); for my $name (keys %{$heap->{cfg}->{device}}){ push @{ $heap->{cfg}->{devices}},$name; } print pp $heap; print "\n-----------------------\n"; foreach my $name (@{ $heap->{cfg}->{devices} }) { my $CFG = $heap->{cfg}->{device}->{$name}->{localfile}; print "$CFG\n"; } print "-----------------------\n"; }
    poj