[EMAIL PROTECTED] wrote:
Hi all,
     I am trying to setup a hash who's values are referance to hash's. Data structure 
should look like this

hash
     1:
           setting 1
           setting 2
     2:
           setting 1
           setting 2
....

This does not look like a HoH, but a HoA.



I would think it can be accomplished with following code, but when I try to print it out it only prints the last setting which it read. Any idea's ??


CODE:
#!perl -w
use strict;
open RD, "input.txt";

Always check that open succeeded.


open RD, "input.txt" or die "Can't open file: $!";


my ( $field,$portsetting, $value, $port, $portnum, %digi, $debug ); $debug=0;


Declaring all of your variables up front reduces the help that 'strict' can provide and generally leads to more problems. It may be that $field is getting reused because even though you are "emptying" it, this isn't clear to me.


while ( <RD> ) {

Let's dispense with $_ it adds confusion when we should be trying to be explicit. Once you don't have to ask questions about references then consider going back to it.


while (my $line = <RD>) {

if(m/^(port)\s\=\s(.*)$/i){$portnum=$2;$portnum++}


Whitespace is our friend, why are we capturing a constant?


if ($line =~ m/^port\s=\s(.*)$/i) {
   $portnum = $1;
}

     $field = {};
     $digi{$portnum} = $field;


Double assignment?


m/^(.*)\s\=\s(.*)$/;

If we are going to capture we should double check that the string is formatted properly, put this into an if.


if ($line =~ m/^(.*)\s=\s(.*)$/) {

There's no real need for the temp variables but if you want them that is fine for readability.

                $portsetting=$1;
                $value=$2;
                $field->{$portsetting}=$value;


print "setting $portsetting -> $digi{$portnum}{$portsetting}\n" if $debug;

                if($portsetting eq 'porttitle'){
                        $value =~ tr /-/ /;
                        $value =~ m/^(\w+)\s+(\w+)/i;

Again if you are going to run a match make sure it succeeds, especially when capturing. As a side note your sample data did not contain this.


                        $field->{$portsetting}=$1;
                        $field->{'type'}=$2;
print "1:$digi{$portnum}{$portsetting}\t2:$digi{$portnum}{'type'}\n" if $debug;
                }

}


# print the whole thing foreach $port ( keys %digi ) { print "$port: { "; for $field ( keys %{ $digi{$port} } ) { print "$field=$digi{$port}{$field} "; } print "}\n"; }


If this is just for debugging take a look at Data::Dumper it is much easier.


Sample DATA

port = 0
bmanset = 0
benable = 1
uarttype = 0
baudrate = 9600
stopbits = 1
databits = 8
parity = 0
flowcontrol = 0
protocol = 1
port = 1
bmanset = 0
benable = 1
uarttype = 0
baudrate = 9600
stopbits = 1
databits = 8
parity = 0
flowcontrol = 0
protocol = 1



Essentially something is very awkward about all of that code, and it can definitely be simplified by using better scoping. You should consider reading, if you haven't already,


perldoc perldsc
perldoc perllol
perldoc perlreftut
perldoc perlref

Here is a stab, untested,

#!/usr/local/bin/perl
use strict;
use warnings;


my %ports;



my $current_port = ''; while (my $line = <DATA>) { if ($line =~ /^port\s=\s(\d+)$/) { $current_port = $1; } elsif ($line =~ /^(.*)\s=\s(.*)$/) { die "Port not set" unless $current_port ne ''; $ports{$current_port}->{$1} = $2; } else { warn "Improperly formatted line: $line"; } }


use Data::Dumper; print Dumper(\%ports);


__DATA__ port = 0 bmanset = 0 benable = 1 uarttype = 0 baudrate = 9600 stopbits = 1 databits = 8 parity = 0 flowcontrol = 0 protocol = 1 port = 1 bmanset = 0 benable = 1 uarttype = 0 baudrate = 9600 stopbits = 1 databits = 8 parity = 0 flowcontrol = 0 protocol = 1

--
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]
<http://learn.perl.org/> <http://learn.perl.org/first-response>




Reply via email to