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

Monks,

I've got the script below where I'm trying to get the values from nested hashes that are a few layers deep and stored in a DBM file.

Storing works fine and retrieving works fine if I'm using a while loop, but fails when using a for loop. I'm getting the error message "Can't use string ("machine1value4") as a SCALAR ref while "strict refs" in use at" blah.

Eventually I want to retrieve the deepest hash values back in to scalars or maybe a regular hash so I can more easily work with them while I'm learning. Retrieving them with a for loop is one step in my mental progression to help me learn as I work on my overall project.

FWIW my overall project involves one script retrieving values from a remote machine and storing them in a file and then having a another script(CGI) read the file and display certain values. The data will be organized first by user, then by machine, and then finally the key/value pairs.

#!/usr/bin/perl #==================================================== # Test script for HoHoH. To run: # ./script -a to build the db file. # ./script -w to print with while loop. # ./script -f to print with for loop(partially fails). #==================================================== use strict; use warnings; use DBM::Deep; use Getopt::Long; my ( $add, $while_print, $for_print ); GetOptions( "add" => \$add, "while_print" => \$while_print, "for_print" => \$for_print ); my $user = 'user1'; my $machine = 'machine1'; if ($add) { my $db = DBM::Deep->new("foo_pm.db"); $db->{$user} = { $machine => { $machine . key1 => "$machine" . 'value1', $machine . key2 => "$machine" . 'value2', $machine . key3 => "$machine" . 'value3', $machine . key4 => "$machine" . 'value4' }, }; } if ($while_print) { my $db = DBM::Deep->new("foo_pm.db"); while ( my ( $outerkey, $value_user ) = each %$db ) { print "The outer key(user) is $outerkey. \n"; while ( my ( $key2, $value_machine ) = each %{ $db->{$outerkey +} } ) { print " The key(machine) is $key2: \n"; while ( my ( $key3, $value ) = each %{ $db->{$outerkey}->{ +$key2} } ) { print " The key is $key3, the value is $value.\n" +; } } } print "\n"; } if ($for_print) { my $db = DBM::Deep->new("foo_pm.db"); while ( my ( $outerkey, $value_user ) = each %$db ) { print "The outer key(user) is $outerkey. \n"; while ( my ( $key2, $value_machine ) = each %{ $db->{$outerkey +} } ) { print " The key(machine) is $key2: \n"; for my $key3 ( keys %{ $db->{$outerkey}->{$key2} } ) { print " The key(machine_key) is $key3\n"; my $value_param = ${ $db->{$outerkey}->{$key2}{$key3} +}; print " The value is $value_param\n"; } } } print "\n"; }
I know the problem is here  my $value_param = ${ $db->{$outerkey}->{$key2}{$key3} }; but I'm baffled that the script is able to get the value from the key but still produces an error message.
I've tried many different combinations but can't seem to find the right one.

Here's a run when using the while loop and is correct.

./script.pl -w The outer key(user) is user1. The key(machine) is machine1: The key is machine1key4, the value is machine1value4. The key is machine1key1, the value is machine1value1. The key is machine1key2, the value is machine1value2. The key is machine1key3, the value is machine1value3.
Here's the failing run when using the for loop.
./script.pl -f The outer key(user) is user1. The key(machine) is machine1: The key(machine_key) is machine1key4 Can't use string ("machine1value4") as a SCALAR ref while "strict refs +" in use at ./script.pl line 50.
Thank-you for your consideration.
  • Comment on Error "Can't use string ("machine1value4") as a SCALAR ref while "strict refs" in use at" from HoHoH
  • Select or Download Code

Replies are listed 'Best First'.
Re: Error "Can't use string ("machine1value4") as a SCALAR ref while "strict refs" in use at" from HoHoH
by ikegami (Patriarch) on Oct 21, 2009 at 02:34 UTC
    You're trying to deref the hash value, but it's not a reference.
    my $value_param = ${ $db->{$outerkey}->{$key2}{$key3} };
    should be
    my $value_param = $db->{$outerkey}->{$key2}{$key3};