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

I am really pleased with myself to be as far as I am using references and at this time I feel it is extremely important for everyone out there to know that I am very greatfull for the time, effort, sweat, blood, and tears, and not to mention hard work that those have put into writing the documentation on anything relating to programming. I would like to give even MORE thanks to those who made the docs on references! Whoa! Those are a total mind blower at first and then all of a sudden *click* you get it! However, I am in the middle of my 'click' and seem to be messing up somewhere.

I am creating (what I feel is) complex data structures and seem to be doing a decent job at making them complex but not too complex (comments welcomed). My problem is getting at the information after its been placed in the structure.

Many may remember my post Advice sought for parsing config file. After thinking about things I decided that I truly needed more work at learning how to create complex data structures, had a go at perldoc perlref and perlreftut and started to whack at the code. I have done a considerable amount of writing and re-writing just to whittle it down to what I have thus far. So, without further adieu I give you the current code. Use Advice sought for parsing config file for a copy of the config file I am using and then any comments would be very much appreciated. I am thinking I am just overlooking something.

#!/usr/local/bin/perl -w use strict; use Env; my $file = "$HOME/archive_bin/configs/dtfr_archiver.conf"; my ($class,$type,$var,$rval,%config); my (@rule,%macro,%rule); open(F,$file) or die("Can't open it: $!\n"); while ( <F> ) { chomp; my $current_line = $_; my $ok = "^(macro|define|rule)"; next if ( /^#/ ); # skip comments next if ( /^\n/ ); # skip newlines and all only-spaces my $check = (/$ok(\s+\w+\s+\{)?/ .. /^\}/); do { if ( $check == 1 ) { $class = $1; $2 =~ /^.*? (\w+)\s+\{/ if $2; # do more checking here $type = $1; # do more checking here next; } if ( $check !~ /E0/ and $check > 1 ) { if ( $current_line =~ /=/ ) { ($var,$rval) = split(/=/,$_); $var =~ tr/ //d; $rval =~ tr/" ;//d; if ( $rval =~ /,/ ) { my @rval = split(/,/,$rval); } } if ( $var and $rval ) { # Ok, create an array. my @rval = split(/,/,$rval); # Create a reference to that array. my $rval = \@rval; # Create a hash of hash references pointing to the array reference for + the # macros. print "type: $type => var: $var -> val: ".join(", ",@$rval) ." +\n"; $macro{$type} = { $var => $rval } if ( $class eq "macro" ); # Do the same for the rules. $rule{$type} = { $var => $rval } if ( $type =~ /^\d+$/ ); } } } if $check; } print "Keys for \%macro: ".join(", ",keys(%macro))."\n"; while ( my ($key, $val) = each(%macro) ) { print "key: $key => vals:\n"; while ( my ($nkey, $nval) = each(%$val) ) { for ( @{$nval} ) { print "\tkey: $nkey -> val = $_\n" if ( $nkey ); } } }

My problem I fear is in the last few lines where I am walking the hash references

This is what I get for now as output:

type: define => var: destination -> val: /u90/gvc_archive/new type: define => var: unkdest -> val: /u90/gvc_archive/tmp type: define => var: runonce -> val: port100 type: arbor_ama => var: regex -> val: /F.*?-P.*?\.(\d+)\.ama/ type: arbor_ama => var: dfield -> val: $1 type: dex => var: regex -> val: /^P.*?_DSC_.*?\.(\d+)\.ama$/ type: dex => var: dfield -> val: $1 type: rpt => var: regex -> val: /^RPT_(\d+)_.*?$/ type: rpt => var: dfield -> val: $1 type: rptnull => var: regex -> val: /^RPT.*?$/ type: rptnull => var: dfield -> val: NULL type: rtcd_everything => var: regex -> val: /.*?/ type: rtcd_everything => var: dfield -> val: 2__ type: arbor1_1 => var: regex -> val: /^F.*?_D(\d+)_.*?PRI_1_1\.ama$/ type: arbor1_1 => var: dfield -> val: $1 type: arbor => var: regex -> val: /^F.*?\.(\d+)\.ama$/ type: arbor => var: dfield -> val: $1 type: usl1 => var: regex -> val: /^USL_.*?_(\d{6})_.*?$/ type: usl1 => var: dfield -> val: $1 type: usl2 => var: regex -> val: /^USL_.*?_(\d{6})$/ type: usl2 => var: dfield -> val: $1 type: uslnull => var: regex -> val: /^USL.*?$/ type: uslnull => var: dfield -> val: NULL type: 10 => var: port -> val: port11, port41, port61, port77, port85 type: 10 => var: macro -> val: rtcd_everything type: 60 => var: port -> val: 87 type: 60 => var: regex -> val: /F.*?\-P.*?_FCC_(\d+)_.*?\.cdr/ type: 60 => var: dfield -> val: $1 type: 60 => var: macro -> val: usl1 type: 60 => var: macro -> val: usl2 type: 100 => var: port -> val: 100 type: 100 => var: regex -> val: /P\d+_(PRI|SEC|TPP)_.*?\.(\d{4})\.ama/ type: 100 => var: dfield -> val: $2 type: 110 => var: port -> val: 110 type: 110 => var: regex -> val: /P\d+_.*?\.(\d{6})\.(EMR|emr)/ type: 110 => var: dfield -> val: $1 type: 120 => var: port -> val: 125 type: 120 => var: regex -> val: /F.*?-P.*?_(.*?)_.*?/ type: 120 => var: dfield -> val: $1 type: 120 => var: macro -> val: usl2 type: 130 => var: port -> val: 132 type: 130 => var: regex -> val: /F.*?P.*?FCC_(\d+)_\d+\.cdr/ type: 130 => var: dfield -> val: $1 type: 130 => var: macro -> val: usl1 type: 130 => var: macro -> val: usl2 type: 130 => var: macro -> val: rpt type: 130 => var: macro -> val: rptnull type: 135 => var: port -> val: 133, 134, 135, 136, 137, 138, 142, 143, + 144 type: 135 => var: macro -> val: arbor_ama, usl1, usl2, rpt, rptnull, a +rbor1_1 type: 225 => var: port -> val: 180 type: 225 => var: macro -> val: rpt, usl type: 230 => var: port -> val: 185 type: 230 => var: macro -> val: usl1, usl2, rpt, rptnull type: 240 => var: port -> val: 187 type: 240 => var: regex -> val: /^F.*?DSC.*?dex\.(\d+)$/ type: 240 => var: dfield -> val: $1 type: 240 => var: macro -> val: usl1, usl2, rpt type: 250 => var: port -> val: 200 type: 250 => var: regex -> val: /P099.*?\.dat/ type: 250 => var: dfield -> val: NULL type: 260 => var: port -> val: 202 type: 260 => var: regex -> val: /^F.*?_mci.*?\.mci/ type: 260 => var: regex -> val: /^F.*?_D(\d+)_.*?\.dat/ type: 260 => var: dfield -> val: $1 type: 260 => var: macro -> val: usl, rpt Keys for %macro: rtcd_everything, rptnull, dex, arbor_ama, usl1, usl2, + arbor, rpt, arbor1_1, uslnull key: rtcd_everything => vals: key: dfield -> val = 2__ key: rptnull => vals: key: dfield -> val = NULL key: dex => vals: key: dfield -> val = $1 key: arbor_ama => vals: key: dfield -> val = $1 key: usl1 => vals: key: dfield -> val = $1 key: usl2 => vals: key: dfield -> val = $1 key: arbor => vals: key: dfield -> val = $1 key: rpt => vals: key: dfield -> val = $1 key: arbor1_1 => vals: key: dfield -> val = $1 key: uslnull => vals: key: dfield -> val = NULL
Notice that all of the values for each hash are not getting dereferenced for some reason. Why? :)

TIA once again for any advice.

_ _ _ _ _ _ _ _ _ _
- Jim
Insert clever comment here...

Replies are listed 'Best First'.
Re: Im missing something small here? (dereferencing complex references)
by trs80 (Priest) on Mar 25, 2002 at 22:40 UTC
    Your assignment to the %macro hash is over writing the last entry because $type is the same for item you want to add:
    $macro{$type} = { $var => $rval } if ( $class eq "macro" );
    should be
    $macro{$type}{$var} = $rval if ( $class eq "macro" );
    You can also get rid of the temp assignment into an array, by doing this for rval:
    my $rval = [ split(/,/,$rval) ];
Re: Im missing something small here? (dereferencing complex references)
by RMGir (Prior) on Mar 25, 2002 at 20:58 UTC
    It probably has nothing to do with your problem, but

    my $rval = \@rval;

    is likely to reuse the same lexical array every time, isn't it? (quick typing ensues as I test that out....)

    $ perl -e'for(1..10){my @rv; my $ref=\@rv; print "$ref\n"}' ARRAY(0x810218c) ARRAY(0x810218c) ARRAY(0x810218c) ARRAY(0x810218c) ARRAY(0x810218c) ARRAY(0x810218c) ARRAY(0x810218c) ARRAY(0x810218c) ARRAY(0x810218c) ARRAY(0x810218c)

    I think what you wanted was

    my $rval=[@rval];

    --
    Mike