Beefy Boxes and Bandwidth Generously Provided by pair Networks
Come for the quick hacks, stay for the epiphanies.
 
PerlMonks  

Pushing Data into a Hash

by vbrtrmn (Pilgrim)
on Jul 28, 2003 at 02:35 UTC ( [id://278316]=perlquestion: print w/replies, xml ) Need Help??

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

I'm a bit stuck with this piece of code. I can't seem to wrap my brain around a good way to do it. Maybe I've been thinking about it too long.

I basically have some data that I've formatted from my company's ACL, which was provided in HTML format (I'll leave all of that junk out). The code below obviously won't work, it will always miss adding the last entry to the hash. Can someone throw me a bone?

unless($_ =~ /^\d+\.\d+\.\d+\.\d+/) { unless ($key eq "") { $CoreRegR{$key} = \@rangelist; } @rangelist = (); $key = $_; } else { push(@rangelist,$_); }

Here's what the data looks like:

Server1 Name 192.168.100.1/27 192.168.101.2/32 Server2 Name Server3 Name 192.168.102.3/31 192.168.103.4/30 192.168.104.5/28 Server4 Name 10.100.2.1/31 10.101.2.2/32 10.102.2.3/28 Server5 Name 10.103.2.4/29 10.104.2.5/27

thanks in advance

--
paul

Replies are listed 'Best First'.
Re: Pushing Data into a Hash
by bobn (Chaplain) on Jul 28, 2003 at 03:12 UTC

    As near as I can tell, you want somehting like this:

    #!/usr/bin/perl -w use Data::Dumper; while(<DATA>) { chomp; next unless $_; if($_ =~ /^\d+\.\d+\.\d+\.\d+/) { push @{$CoreRegR{$key}},$_; # first time, for new server, auto-vivifies # $CoreRegR{$key} as arrayref. # first and all other times, # pushes the ip range onto the anon array that # $CoreRegR{$key} refers to. } else { $key = $_; } } print Dumper(\%CoreRegR); __DATA__ Server1 Name 192.168.100.1/27 192.168.101.2/32 Server2 Name Server3 Name 192.168.102.3/31 192.168.103.4/30 192.168.104.5/28 Server4 Name 10.100.2.1/31 10.101.2.2/32 10.102.2.3/28 Server5 Name 10.103.2.4/29 10.104.2.5/27
    which produces this output:
    $VAR1 = { 'Server3 Name' => [ '192.168.102.3/31', '192.168.103.4/30', '192.168.104.5/28' ], 'Server4 Name' => [ '10.100.2.1/31', '10.101.2.2/32', '10.102.2.3/28' ], 'Server5 Name' => [ '10.103.2.4/29', '10.104.2.5/27' ], 'Server1 Name' => [ '192.168.100.1/27', '192.168.101.2/32' ], 'Server2 Name' => [] };

    Although I use 'unless' in modifiers (as in above, next unless $_), I find it hard to think about full blown unless-else constructs - maybe that's just me, but my head gets all tangled up.

    As noted by a previous poster, use Data::Dumper - it is invaluable in figuring out what is going on.

    Update: fixed where I called an arrayref a hashref wrongly.

    --Bob Niederman, http://bob-n.com
Re: Pushing Data into a Hash
by pzbagel (Chaplain) on Jul 28, 2003 at 02:57 UTC

    One key thing that I think you are doing incorrectly is you are clearing the contents of @rangelist after you store a reference to it in the hash. In the end, each hash value will be a reference pointing to the exact same array, which will probably be empty.

    @rangelist = (); #just keeps dumping the data stored there.

    Change @rangelist into $rangelist and make it a reference to an anonymous array. Then when you need another array, you just declare another one and assign it to $rangelist.

    Like so:

    unless($_ =~ /^\d+\.\d+\.\d+\.\d+/) { unless ($key eq "") { $CoreRegR{$key} = $rangelist; } $rangelist = []; $key = $_; } else { push(@$rangelist,$_); }

    HTH

    P.S. Check out the standard Data::Dumper module to print out complex data structures so you can more easily see what is being built.

Re: Pushing Data into a Hash
by Zaxo (Archbishop) on Jul 28, 2003 at 03:07 UTC

    You show a sort of tattered remnant of code, so I'm not sure what the best fix is. It looks like you want to do this,

    # loop starts upward of here # $key must be scoped outside the loop chomp; if (/^\d+\.\d+\.\d+\.\d+$/) { next unless $key; push @{$CoreRegR{$key}}, $_; # Alt. replace the prev 2 lines with # push @{$CoreRegR{ $key || 'unnamed host' }}, $_; } else { $key = $_ } # ...
    It is simpler to push things straight into the HoA element when they are encountered than to build a named array and shove it in when the next key is found. As you observed, that loses the last set of addresses.

    After Compline,
    Zaxo

Re: Pushing Data into a Hash
by saintbrie (Scribe) on Jul 28, 2003 at 03:31 UTC

    My solution so closely resembled zaxo's that I removed it. The difference was that I used the existing code and changed the data by adding a data terminator, and changed

    $CoreRegR{$key} = \@rangelist

    to

    $CoreRegR{$key} = [@rangelist]

    After 10.104.2.5/27, just add an "END OF DATA" to the data and the code should work. This solution leaves you with an empty array ref for Server2 Name, instead of not including it with in the hash.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://278316]
Approved by Zaxo
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others wandering the Monastery: (5)
As of 2024-04-16 17:26 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found