Beefy Boxes and Bandwidth Generously Provided by pair Networks
Don't ask to ask, just ask
 
PerlMonks  

Adding an Entire Class B IP Range to an Array

by Dru (Hermit)
on Mar 31, 2005 at 16:49 UTC ( [id://443883]=perlquestion: print w/replies, xml ) Need Help??

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

Hello Monks,

I'm trying to create an array which includes all ip's within a class B range from 1-254 for both the 3rd and 4th octet. I can get the third octet included, but can't figure out how to include the fourth.
my @hosts = map q|192.168.| . $_, 1..254; for (@hosts){ print "$_\n"; } ~
Any help is greatly appreciated.

Thank You,
Dru

Replies are listed 'Best First'.
Re: Adding an Entire Class B IP Range to an Array
by merlyn (Sage) on Mar 31, 2005 at 17:19 UTC
      Beautiful. I might have to use this instead.
      Can someone explain this, please? it works, but I don't understand it.

        By reading the docs on glob, we note that this is now implemented in terms of File::Glob. Check that documentation out for File::Glob, and look for GLOB_BRACE.

        Here it happens that knowing how csh works is advantageous when coding perl.

      I thought this might progress the braced expressions together (giving '192.168.1.1', '192.168.2.2', '192.168.3.3', etc.) so I wanted to test it. But when I did, it didn't even do that. Instead it gives:

      192.168.1.
      192.168.2.
      192.168.3.
      192.168.4.
      192.168.5.
      192.168.6.
      192.168.7.
      192.168.8.
      192.168.9.
      192.168.10.
      192.168.11.
      192.168.12.
      192.168.13.
      192.168.14.
      192.168.15.
      192.168.16.
      192.168.17.
      192.168.18.
      192.168.19.
      192.168.20.
      ...
      
      Is there a limit to glob expansion? It works as expected if I change 1..254 to 1..6, for example.

Re: Adding an Entire Class B IP Range to an Array
by moot (Chaplain) on Mar 31, 2005 at 16:52 UTC
      Thanks for the tip. Here's how I've accomplished it:
      use Net::IP; my $ip = new Net::IP ('192.168.1.1 - 192.168.254.254') || die; do { print $ip->ip(), "\n"; } while (++$ip);
      BTW..I haven't seen a do/while loop since my C++ class in college. I wasn't even aware Perl had one.

        That program prints '192.168.1.255', '192.168.2.0', etc. Is that what you wanted?

        ... 192.168.1.254 192.168.1.255 192.168.2.0 192.168.2.1 ... 192.168.2.254 192.168.2.255 192.168.3.0 192.168.3.1 ...
Re: Adding an Entire Class B IP Range to an Array
by ikegami (Patriarch) on Mar 31, 2005 at 17:10 UTC

    There's no such thing as class B anymore. Subnets are divided quite arbitrarily. But let's say you divided 192.168.0.0/16 into 256 nets of size /24:

    use NetAddr::IP (); my @hosts; foreach (0..255) { my $net_addr = NetAddr::IP->new("192.168.$_.0/24"); my $net_broadcast = $net_addr->broadcast(); push(@hosts, $net_addr->addr()) while ++$net_addr != $net_broadcast; } print("$_$/") foreach @hosts;

    Or if flexibility is not needed:

    my @hosts = map { my $pre = "192.168.$_."; map { $pre.$_ } 1..254 } 0..255;

    A more efficient version:

    my @hosts; foreach (0..255) { my $pre = "192.168.$_."; foreach (1..254) { push(@hosts, $pre.$_); } }

    Update: Here's the provided glob solution adjusted to also provide 192.168.0.{1-254} and 192.168.255.{1-254}:

    my $octet = join(',', 1..254); my @hosts = glob("192.168.{0,$octet,255}.{$octet}");
Re: Adding an Entire Class B IP Range to an Array
by ambs (Pilgrim) on Mar 31, 2005 at 16:52 UTC
    My first idea. Not small, but works.
    my @hosts = map q|192.168.| . $_, 1..254; @hosts = map { my @h; my $ip = $_; push @h, "$ip.$_" for (1..254); @h } @hosts; for (@hosts){ print "$_\n"; }

    Alberto Simões

Re: Adding an Entire Class B IP Range to an Array
by Fletch (Bishop) on Mar 31, 2005 at 17:46 UTC

    And yet another way . . .

    use IO::Socket qw( inet_aton inet_ntoa ); my $start = unpack( "N", inet_aton( "192.168.0.0" ) ); my @addrs; push @addrs, inet_ntoa( pack( "N", $start++ ) ) for 1..(256*256);

    Addendum: Net::Netmask also provides methods for generating the nth address in a given CIDR block.

Re: Adding an Entire Class B IP Range to an Array
by Jaap (Curate) on Mar 31, 2005 at 16:59 UTC
    You can use map from within map which would be quite ugly for more than 2 levels an quite hard for n levels where n is determined at runtime.
    my @hosts = map {my $i = $_; map {"192.168.$i.$_"} 1 .. 254} 1 .. 254;
      [nesting maps] would be quite hard for n levels where n is determined at runtime
      That's what Algorithm::Loops 'NestedLoops' is for. And (because I need to practice using it) the solution corresponding to yours would be
      use Algorithm::Loops 'NestedLoops'; my @hosts = NestedLoops([([1..254])x2], sub { "192.168.$_[0].$_[1]" }) +;

      Caution: Contents may have been coded under pressure.
      The outer 1..254 (3rd octet) should be 0..255 if you don't wanna skip 510 valid addresses.
Re: Adding an Entire Class B IP Range to an Array
by Tanktalus (Canon) on Mar 31, 2005 at 17:09 UTC

    TMTOWTDI. Let's say we made this into the string "192.168.[1:254].[1:254]". Now we have something that this snippet could handle quite cleanly. Adding additional dynamic octets is pretty simple, too.

Re: Adding an Entire Class B IP Range to an Array
by gam3 (Curate) on Mar 31, 2005 at 17:25 UTC
    for my $i (0..255) { for my $j (1..254) { printf("192.168.%d.%d\n", $i, $j); push @hosts, sprintf("192.168.%d.%d", $i, $j); } }
    -- gam3
    A picture is worth a thousand words, but takes 200K.
Re: Adding an Entire Class B IP Range to an Array
by Random_Walk (Prior) on Apr 01, 2005 at 08:56 UTC

    As the range is just another representation of a count from 0 .. (256*256)-1 I thought a pack/unpack solution may be fun.

    #!/usr/bin/perl use warnings; use strict; my $base="192.168."; my @adds; for (1..65535){ $_=sprintf("%04x",$_); /(..)(..)/; $_=join".", unpack "S*",(pack "H4", "00$1").(pack "H4", "00$2"); push @adds, $base.$_ unless /255|\.0$/; } # lets look at a few print $adds[rand $#adds], $/ for (1..100);
    And I know the OP said he wanted all the vals in an array but for some an itterator that returns the next val or undef when all used up may be more useful so here is one for fun.
    #!/usr/bin/perl use warnings; use strict; sub init_adds { my $base=shift; my $a=1; my $b=0; return sub { if ($a==255) { $b++; return undef if $b==256; $a=1; } return ("$base.$b.".$a++); } } my $gen=init_adds(192.168); while (my $val = &$gen) { print $val, $/ ; }

    Cheers,
    R.

    Pereant, qui ante nos nostra dixerunt!

Log In?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others lurking in the Monastery: (4)
As of 2024-04-19 12:04 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found