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

I have a below program and I am not doing it right. Currently, only last ip pool is going in since I am putting them w/ key to values(so only last one shows up when I print).
How can I aggregate and assign them to server_1 so that when I print below will show up?
__output I want__ (which I am not getting) server_1 10.1.1.1 10.1.1.2 10.1.1.3 10.1.1.4 10.1.1.5 192.168.1.1 192.168.1.2 while ( <DATA> ) { my @array_ip; chomp; my ($swit,$server,$ip_range) = split; my ($b_real_ip,$b_ip, $e_ip) = $ip_range =~ m#(\d+\.\d+\.\d+\.) +(\d+)\-(\d+)#; my $b_ip_copy = $b_ip; my @ip_g; while ( $b_ip_copy <= $e_ip ) { my $b_ip_final = join('',$b_real_ip,$b_ip_copy); push @ip_g , $b_ip_final; ++$b_ip_copy; } $HoA{ join('_',$swit,$server) } = \@ip_g; } __DATA__ server 1 10.1.1.1-10.1.1.5 server 2 192.168.1.1-192.168.1.5 server 1 192.168.1.1-192.168.1.2

Replies are listed 'Best First'.
Re: assigning hash key to reference of array question
by Eliya (Vicar) on Feb 28, 2011 at 20:39 UTC

    Another suggestion:

    #!/usr/bin/perl -w use strict; use Socket; my %HoA; while (<DATA>) { chomp; my ($swit, $server, $ip_range) = split; my ($start_ip, $end_ip) = map unpack("N", inet_aton($_)), split /- +/, $ip_range; my $name = "${swit}_$server"; for ($start_ip .. $end_ip) { push @{ $HoA{$name} }, inet_ntoa(pack "N", $_); } } use Data::Dumper; print Dumper \%HoA; __DATA__ server 1 10.1.1.1-10.1.1.5 server 2 192.168.1.1-192.168.1.5 server 1 192.168.1.1-192.168.1.2
    $VAR1 = { 'server_2' => [ '192.168.1.1', '192.168.1.2', '192.168.1.3', '192.168.1.4', '192.168.1.5' ], 'server_1' => [ '10.1.1.1', '10.1.1.2', '10.1.1.3', '10.1.1.4', '10.1.1.5', '192.168.1.1', '192.168.1.2' ] };
Re: assigning hash key to reference of array question
by toolic (Bishop) on Feb 28, 2011 at 20:10 UTC
      spark@server1 ~> cat -nv ././././t1 | grep 21 21 push @{ $HoA{ join('_',$swit,$server) } } = @ip_g; spark@server1 ~> perl -c ././././t1 Useless use of push with no values at ././././t1 line 21. Type of arg 1 to push must be array (not list assignment) at ././././t +1 line 21, near "@ip_g;" ././././t1 had compilation errors.
        You need to use a comma instead of an = (just like my code shows).
Re: assigning hash key to reference of array question
by umasuresh (Hermit) on Feb 28, 2011 at 20:35 UTC
    I think this what you are looking for:
    use strict; use warnings; my %HoA; while ( <DATA> ) { my @array_ip; chomp; my ($swit,$server,$ip_range) = split; my ($b_real_ip,$b_ip, $temp, $e_ip) = $ip_range =~ m#(\d+\.\d+\ +.\d+\.)(\d+)\-(\d+\.\d+\.\d+\.)(\d+)#; my $b_ip_copy = $b_ip; my @ip_g; while ( $b_ip_copy <= $e_ip) { my $b_ip_final = join('',$b_real_ip,$b_ip_copy); push @ip_g , $b_ip_final; ++$b_ip_copy; } $HoA{ join('_',$swit,$server,$b_real_ip) } = \@ip_g; } for my $key (sort keys %HoA) { for my $key2 (@{ $HoA{ $key } }) { print "$key\t"; print "$key2\n"; } print "\n"; } __DATA__ server 1 10.1.1.1-10.1.1.5 server 2 192.168.1.1-192.168.1.5 server 1 192.168.1.1-192.168.1.2
Re: assigning hash key to reference of array question
by ikegami (Patriarch) on Feb 28, 2011 at 20:48 UTC
    Simpler?
    use Socket qw( inet_aton inet_ntoa ); while (<DATA>) { my ($swit,$server,$ip_range) = split; $server = "${swit}_$server"; my ($start, $end) = split /-/, $ip_range; my $start_n = unpack('N', inet_aton($start)); my $end_n = unpack('N', inet_aton($end)); for my $ip_n ($start_n..$end_n) { push @{ $servers{$server} }, inet_ntoa(pack('N', $ip_n)); } }

    Update: Ack! Eliya posted the same as this when I was typing this.

Re: assigning hash key to reference of array question
by locked_user sundialsvc4 (Abbot) on Feb 28, 2011 at 20:49 UTC

    When writing code like this, I find that I just have to grab a number-two pencil and a piece of paper and write down what I want the computer to do.   It looks to me like you are unintentionally creating “a reference to a reference.”

    When you put a complex piece of data “into” an array or a hash, what actually happens is that you put “a reference to that data” there. “A reference” is, effectively, a scalar.   It is, in other words, “a Thing,” separate from “the other Thing” that it refers to.   You need to be sure that, when the dust settles, you wind up with “two references to the same Underlying Object,” not “a reference to a reference.”

    It’s tricky to do.   (Heck, it’s hard enough to explain...)

      It's actually very simple to map out data structures. If it's tricky, something has gone wrong.

      A collection of servers is a hash of servers keyed by name.
      A server is a collection of IP addresses.
      A collection of IP addresses is an array of IP addresses in dotted form.

      It looks to me like you are unintentionally creating “a reference to a reference.”

      His structure is fine. The problem is that he was replacing the collection of IP addresses when he wanted to add to it.