Professional Web Applications Themes

Hash ref's of hash's - PERL Beginners

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 ..... 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"; my ( $field,$portsetting, $value, $port, $portnum, %digi, $debug ); $debug=0; while ( <RD> ) { if(m/^(port)\s\=\s(.*)$/i){$portnum=$2;$portnum++} $field = {}; $digi{$portnum} = $field; m/^(.*)\s\=\s(.*)$/; $portsetting=$1; $value=$2; $field->{$portsetting}=$value; print "setting $portsetting ...

  1. #1

    Default Hash ref's of hash's


    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
    .....

    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";

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

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

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

    m/^(.*)\s\=\s(.*)$/;
    $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;
    $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";
    }

    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

    mgoland@optonline.net Guest

  2. #2

    Default Re: Hash ref's of hash's

    net wrote: 

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

    Always check that open succeeded.

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

    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.
     

    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>) {
     

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

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

    Double assignment?
     

    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.
     
     

    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.
     

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

    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
    Wiggins Guest

  3. #3

    Default Re: Hash ref's of hash's

    net wrote: 

    Hello,
     


    Perhaps this will do what you want:

    #!perl -w
    use strict;
    use Data::Dumper;

    open RD, 'input.txt' or die "Cannot open 'input.txt' $!";

    my ( %data, $temp );
    while ( <DATA> ) {
    chomp;
    my ( $name, $value ) = split /\s*=\s*/ or next;
    if ( exists $temp->{ $name } or eof DATA ) {
    $data{ $temp->{ port } } = $temp;
    $temp = { $name, $value };
    next;
    }
    $temp->{ $name } = $value;
    }

    print Dumper \%data;

    __END__



    John
    --
    use Perl;
    program
    fulfillment
    John Guest

  4. #4

    Default Re: Hash ref's of hash's

    "John W. Krahn" wrote: 

    Oops, forgot a line. :-)

    $temp->{ $name } = $value if eof DATA;
     


    John
    --
    use Perl;
    program
    fulfillment
    John Guest

  5. #5

    Default Re: Hash ref's of hash's

    John,
    this code didn't work for me. Although I did have to change <DATA> to
    <RD>;
    ----- Original Message -----
    From: "John W. Krahn" <org>
    To: < >
    Sent: Friday, April 02, 2004 7:47 PM
    Subject: Re: Hash ref's of hash's

     
    >
    > Hello,
    > [/ref]
    Data [/ref]
    try [/ref]
    idea's ?? [/ref]
    $debug; [/ref]
    $debug; 
    >
    >
    > Perhaps this will do what you want:
    >
    > #!perl -w
    > use strict;
    > use Data::Dumper;
    >
    > open RD, 'input.txt' or die "Cannot open 'input.txt' $!";
    >
    > my ( %data, $temp );
    > while ( <DATA> ) {
    > chomp;
    > my ( $name, $value ) = split /\s*=\s*/ or next;
    > if ( exists $temp->{ $name } or eof DATA ) {
    > $data{ $temp->{ port } } = $temp;
    > $temp = { $name, $value };
    > next;
    > }
    > $temp->{ $name } = $value;
    > }
    >
    > print Dumper \%data;
    >
    > __END__
    >
    >
    >
    > John
    > --
    > use Perl;
    > program
    > fulfillment
    >
    > --
    > To unsubscribe, e-mail: org
    > For additional commands, e-mail: org
    > <http://learn.perl.org/> <http://learn.perl.org/first-response>
    >
    >[/ref]


    Mark Guest

  6. #6

    Default Re: Hash ref's of hash's

    Mark Goland wrote: 

    Probably because he use the sample data in the DATA filehandle.

    His code works correctly near as I can tell; so -
    My question is - is your data actually in this format?
     [/ref][/ref]


    Using John's code:

    #!perl -w
    use strict;
    use Data::Dumper;

    # open RD, 'input.txt' or die "Cannot open 'input.txt' $!";

    my ( %data, $temp );

    while ( <DATA> ) {
    chomp;
    my ( $name, $value ) = split /\s*=\s*/ or next;
    if ( exists $temp->{ $name } or eof DATA ) {
    $data{ $temp->{ port } } = $temp;
    $temp = { $name, $value };
    next;
    }
    $temp->{ $name } = $value;
    }

    print Dumper \%data;

    __END__
    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


    I get:

    $VAR1 = {
    '1' => {
    'baudrate' => '9600',
    'flowcontrol' => '0',
    'uarttype' => '0',
    'databits' => '8',
    'stopbits' => '1',
    'port' => '1',
    'benable' => '1',
    'parity' => '0',
    'bmanset' => '0'
    },
    '0' => {
    'protocol' => '1',
    'baudrate' => '9600',
    'flowcontrol' => '0',
    'uarttype' => '0',
    'databits' => '8',
    'stopbits' => '1',
    'port' => '0',
    'benable' => '1',
    'parity' => '0',
    'bmanset' => '0'
    }
    };

    Wc Guest

  7. #7

    Default Re: Hash ref's of hash's


    ----- Original Message -----
    From: "Wiggins d'Anconia" <org>
    To: <net>
    Cc: <org>
    Sent: Thursday, April 01, 2004 9:24 PM
    Subject: Re: Hash ref's of hash's

     [/ref]
    Data structure should look like this 
    >
    > This does not look like a HoH, but a HoA.[/ref]
    Reply no, this is HoH...perhaps beter diagramed as :

    NY =>
    port 1 =>
    setting 1
    setting 2
    CA =>
    .....
    ...... [/ref]
    try to print it out it only prints the last setting which it read. Any
    idea's ?? 
    >
    > Always check that open succeeded.
    >
    > open RD, "input.txt" or die "Can't open file: $!";

    >
    > 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.[/ref]
    Good point, I'll consider it
     
    >
    > 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.[/ref]
    This is a stylistic argument 
    >
    > Whitespace is our friend, why are we capturing a constant?[/ref]
    Good point, I was debuging code and didn't remove it
     
    >
    > Double assignment?[/ref]
    For clarity
     
    >
    > 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(.*)$/) {[/ref]
    Agreed... 
    I need this so I can remove any '-' in a field 'porttitle', thats is why
    I do tr and create a new field TYPE. Perhaps this can be avoided with a
    beter regex. I do apoligize for nto providing example in my data...will
    append a new set to thread
     
    > [/ref]
    $debug; 
    >
    > 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.
    > [/ref]
    $debug; 
    >
    > If this is just for debugging take a look at Data::Dumper it is much[/ref]
    easier. 
    >
    > 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: org
    > For additional commands, e-mail: org
    > <http://learn.perl.org/> <http://learn.perl.org/first-response>
    >
    >[/ref]

    data to reflect porttitle field
    port = 17
    bmanset = 0
    benable = 1
    uarttype = 0
    baudrate = 9600
    stopbits = 1
    databits = 8
    parity = 0
    flowcontrol = 0
    protocol =
    porttitle = ny1-SUN
    port = 18
    bmanset = 0
    benable = 1
    uarttype = 0
    baudrate = 9600
    stopbits = 1
    databits = 8
    parity = 0
    flowcontrol = 0
    protocol =
    porttitle = ny2 -IBM
    port = 19
    bmanset = 0
    benable = 1
    uarttype = 0
    baudrate = 9600
    stopbits = 1
    databits = 8
    parity = 0
    flowcontrol = 0
    protocol =
    porttitle = ny1 SUN-
    port = 20
    bmanset = 0
    benable = 1
    uarttype = 0
    baudrate = 9600
    stopbits = 1
    databits = 8
    parity = 0
    flowcontrol = 0
    protocol =
    porttitle = ny1 SUN
    port = 21
    bmanset = 0
    benable = 1
    uarttype = 0
    baudrate = 9600
    stopbits = 1
    databits = 8
    parity = 0
    flowcontrol = 0
    protocol =
    porttitle = ny1


    Mark Guest

  8. #8

    Default Re: Hash ref's of hash's

    Mark Goland wrote:
     

    What code? I see nothing above this to indicate what you are referring to.

    Joseph

    R. Guest

Similar Threads

  1. iterating through hash of hash references
    By Andrew in forum PERL Beginners
    Replies: 7
    Last Post: March 3rd, 10:49 PM
  2. hash of hash of array slices
    By Paul Kraus in forum PERL Beginners
    Replies: 6
    Last Post: January 26th, 05:55 PM
  3. Sort a hash based on values in the hash stored as arrays of hashes
    By Tore Aursand in forum PERL Miscellaneous
    Replies: 3
    Last Post: September 16th, 10:14 AM
  4. Another reference question (hash of hash references)
    By Tim Musson in forum PERL Beginners
    Replies: 2
    Last Post: August 8th, 01:11 PM

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139