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

I am reading a file and creating a hash, however I need one of the hash values to contain another (embedded) hash. Here is the code:
sub rd_template { my (%mymsg, %msg48, $msg, $key, $val, $msg48, $key48, $val48); open FH, $opt_f or die "Can't open $opt_f: $!"; while (<FH>) { chomp; ($key, $val) = split /=>/; if ($key == 48) { ($key48, $val48) = split /=>/; $msg48{$key48} = $val48; } $msg{$key} = $val; } close FH or die "Can't close $opt_f: $!"; my @temp = %msg; # testing to see the hash quickly.. print "@temp\n"; }
Here is a sample file, note that where the key 48 in the file and below is where I would like the data read into an embedded hash, any help would be great!:
MTI=>1100 2=>4000000000000001 3=>003000 4=>000000010000 11=>666666 12=> 14=>0404 22=>B00101200041 24=>100 41=>0009 42=>0009000101 48=> 2=>01 02 3=>5555555

Thanks in Advance!

Replies are listed 'Best First'.
Re: Hash in a hash value
by halley (Prior) on Jun 03, 2003 at 17:28 UTC

    See perllol and perlreftut to begin.

    A hash associates string keys with scalar values. So you can't embed a hash into another hash's value, directly. Instead, you embed a reference to a hash, since references are scalar.

    A major help in learning the Perl data structures is Data::Dumper. Build a structure, dump it out to see how Perl understands it, in Perl syntax.

    --
    [ e d @ h a l l e y . c c ]

Re: Hash in a hash value
by pzbagel (Chaplain) on Jun 03, 2003 at 18:02 UTC

    I'm not clear on whether you want all the lines following the 48 key to be in the referenced hash? If so, you need to change the contents of the if statement like this:

    if ($key == 48) { my %msg48; while(<FH>){ chomp; ($key48, $val48) = split /=>/; $msg48{$key48} = $val48; } $msg{$key}=\%msg48; } else{ $msg{$key} = $val; }

    Notice how the $msg{$key} assignment had to move inside the else clause at the end there. This is because you want to assign a reference to key 48 but just assign $val every other time. Another option would be to lose the else and just assign the reference to the hash to val:

    #Change: $msg{$key}=\%msg48; #to $val=\%msg48; #And lose the else around: $msg{$key} = $val;

    You get the exact same result that way with a little less fuss, although you could argue that is a little more difficult to read. Finally throw a:

    use Data:Dumper;

    at the top of your code and then you can print your hashes using the Dumper function which is a lot prettier than forcing it to an array!

    print Dumper(\%msg);

    Notice that Data::Dumper expects references to variables.

    HTH

    Addendum: If you want only the next line of your data file to be included in the hash basically remove the while from inside the if statement:

    if ($key == 48) { my %msg; $_=<FH>; chomp; ($key48, $val48) = split /=>/; $msg48{$key48} = $val48; $val=\%msg48; }
      pzbagel, thanks for the input, that is essentially what I wanted to accomplish, I will take your suggestion to use Data:Dumper; as well. Again, thanks for the input! much appreciated
      djbiv