http://www.perlmonks.org?node_id=244996

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

Hello,
I've made several attempts at creating a complex data structure using the following data:
KEY: request_1.3.6.1.2.1.2.2.1.12.27 OID: 1.3.6.1.2.1.2.2.1.11.27 NAME: ifInUcastPkts.27 OID: 1.3.6.1.2.1.2.2.1.15.27 NAME: ifInUnknownProtos.27 OID: 1.3.6.1.2.1.2.2.1.14.27 NAME: ifInErrors.27 OID: 1.3.6.1.2.1.2.2.1.13.27 NAME: ifInDiscards.27 OID: 1.3.6.1.2.1.2.2.1.18.27 NAME: ifOutNUcastPkts.27 OID: 1.3.6.1.2.1.2.2.1.17.27 NAME: ifOutUcastPkts.27 OID: 1.3.6.1.2.1.2.2.1.20.27 NAME: ifOutErrors.27 OID: 1.3.6.1.2.1.2.2.1.19.27 NAME: ifOutDiscards.27 OID: 1.3.6.1.2.1.2.2.1.10.27 NAME: ifInOctets.27 OID: 1.3.6.1.2.1.2.2.1.16.27 NAME: ifOutOctets.27 OID: 1.3.6.1.2.1.1.3.0 NAME: sysUpTime.0 OID: 1.3.6.1.2.1.2.2.1.5.27 NAME: ifSpeed.27 OID: 1.3.6.1.2.1.2.2.1.3.27 NAME: ifType.27 Error Status No error KEY: response_1.3.6.1.2.1.2.2.1.12.27 OID: 1.3.6.1.2.1.2.2.1.11.27 NAME: ifInUcastPkts.27 OID: 1.3.6.1.2.1.2.2.1.15.27 NAME: ifInUnknownProtos.27 OID: 1.3.6.1.2.1.2.2.1.14.27 NAME: ifInErrors.27 OID: 1.3.6.1.2.1.2.2.1.13.27 NAME: ifInDiscards.27 OID: 1.3.6.1.2.1.2.2.1.18.27 NAME: ifOutNUcastPkts.27 OID: 1.3.6.1.2.1.2.2.1.17.27 NAME: ifOutUcastPkts.27 OID: 1.3.6.1.2.1.2.2.1.20.27 NAME: ifOutErrors.27 OID: 1.3.6.1.2.1.2.2.1.19.27 NAME: ifOutDiscards.27 OID: 1.3.6.1.2.1.2.2.1.10.27 NAME: ifInOctets.27 OID: 1.3.6.1.2.1.2.2.1.16.27 NAME: ifOutOctets.27 OID: 1.3.6.1.2.1.1.3.0 NAME: sysUpTime.0 OID: 1.3.6.1.2.1.2.2.1.5.27 NAME: ifSpeed.27 OID: 1.3.6.1.2.1.2.2.1.3.27 NAME: ifType.27 Error Status No error
I'm trying to use the key variable as a key in a hash, and populate the hash with an array of OID, and NAME, and finally have a value or entry in the hash for the Error status

This is my code snippet below:

push(@temp, $hash) if (defined($key)); $hash = {FRAME => $key}; if ($_ =~ /Simple Network Management Protocol/) { $hash->{SNMP} = {SNMP_LIST => []}; } elsif ($_ =~ /\s*SNMP\:\s+Object\s+\=\s+(.+)/) { $oid_list->{OID} = $oid; $oid_list->{NAME} = $name; } elsif ($_ =~ /\s*SNMP\:\s*\n/) { push(@{$hash->{SNMP}->{SNMP_LIST}}, $oid_list); }
I have a data file that I'm extracting the information from, and the information above is what I've extracted.

Any ideas or suggestions?

Replies are listed 'Best First'.
Re: Data Structure help
by fruiture (Curate) on Mar 21, 2003 at 20:40 UTC

    Hmmm...

    my %all_the_stuff = (); my $current; while( <> ){ chomp; next unless length; if( m/^KEY: (.+)/ ){ $current = { OID => [], #you migth want to put these two NAME => [], # together, i don't know ERROR => undef, }; $all_the_stuff{ $1 } = $current } next unless $current; if( m/^(OID|NAME): (.+)/ ){ push @{$current->{$1}},$2 } elsif( m/^Error Status (.+)/ ){ $current->{ERROR} = $1; $current = undef; #error status is final statement } }

    See perlref,perllol, perldsc and perhaps perlre. The code is untested and not to be used without careful analysis.

    --
    http://fruiture.de
Re: Data Structure help
by BrowserUk (Patriarch) on Mar 21, 2003 at 21:11 UTC

    Call me confused, but I can't see how your code snippet relates to the sample data you provided? You have two regex matching against /\s*SNMP\:.../, and one matching /Simple Network Management Protocol/ but the text SNMP does not appear anywhere in your data?

    The other peice of information that is missing from your post is an indication of how you wish to use this data structure once it is built. What are you going to do with it?

    A large amount of the content of the sample data is repetitious. Whilst it is reasonably easy to build a datastructure to hold that data as is, depending what information you wish to extract from it, it may well be better to consolidate the common elements of the repetitios parts. For example, within each of the sections of the data, all the OID's seem only to vary in the last 2 elements. It might therefore make sense, to eliminate the common prefixes and store the varient parts as sub keys of a hash, under a parent key of the invarient part. rather than stuffing the whole lot in an array. It would also appear that there is some relationship between the NAME: element and the paired OID: element? If this is the case, rather than storing them in parallel arrays, you could pair them as key/value pairs in a hash.

    What, if any of the above observations of the data, have any relevance to the application at hand, only you will know, as you haven't explained what that application is. The point being is that there are several ways that you could build a structure to contain the data, but that choosing the best one for your application will depend upon how you need to process that data once you have encapsulated it.


    Examine what is said, not who speaks.
    1) When a distinguished but elderly scientist states that something is possible, he is almost certainly right. When he states that something is impossible, he is very probably wrong.
    2) The only way of discovering the limits of the possible is to venture a little way past them into the impossible
    3) Any sufficiently advanced technology is indistinguishable from magic.
    Arthur C. Clarke.
Re: Data Structure help
by Enlil (Parson) on Mar 21, 2003 at 21:19 UTC
    Heres my take on this:
    use strict; use warnings; use Data::Dumper; my %key_hash; local $/ = "\n\n"; while ( <DATA> ) { if ( /^KEY: ([^\n]+)/ ) { my $current_key = $1; while ( m/OID: ([^\n]+)\nNAME: ([^\n]+)|Error Status (.*)/g ) { if ( defined $3 ) { $key_hash{$current_key}{Error_Status} = $3; } else { push @{$key_hash{$current_key}{OID_NAME}}, [$1,$2]; } } } } print Dumper \%key_hash;
    Resulting in a structure like:

    hope this helps..

    You might want to take a look at perldsc

    -enlil