Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl: the Markov chain saw
 
PerlMonks  

Reg Ex to find IP address in range

by stew (Scribe)
on Aug 28, 2003 at 16:20 UTC ( [id://287429]=perlquestion: print w/replies, xml ) Need Help??

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

Hi,

I am trying to determine if a clients IP address is within a certain range. The first two node are fixed so that's not a problem - the last two can be anywhere between 0 and 55 each ie xxx.xxx.0.55 - good xxx.xxx.56.56 - bad

I initially tried
/^111\.255\.(([0-5])|([0-5]{2}))\.(([0-5])|([0-5]{2}))$/
but it didn't take me long to figure out that xxx.xxx.48.55 would fail DOH!

It's been a long hard day, if anyone has a quick answer to end my frustration that would be most welcome

Replies are listed 'Best First'.
Re: Reg Ex to find IP address in range
by CombatSquirrel (Hermit) on Aug 28, 2003 at 16:29 UTC
    my @parts = split /\./ $address; return (@parts == 4 and $parts[0] == 111 and $parts[1] == 255 and (($parts[2] > 0 and $parts[2] < 56 and $parts[3] >= 0 and $parts[3] < 56) or ($parts[2] == 0 and $parts[3] == 0)));
    Cheers,
    CombatSquirrel.
    Entropy is the tendency of everything going to hell.
Re: Reg Ex to find IP address in range (link to relevant thread)
by ybiC (Prior) on Aug 28, 2003 at 17:09 UTC
Re: Reg Ex to find IP address in range
by gjb (Vicar) on Aug 28, 2003 at 16:34 UTC

    First of, I assume your IP address is actually valid and in the format you mention in your post.

    Now for your problem: why make life hard? The code below is quite simple:

    my @bytes = split(/\./, $ip); if ($bytes[2] <= 55 && $bytes[3] <= 55) { # ok }

    You may -- or even should -- want to look at Net::IP, especially at the bincomp function.

    Hope this helps, -gjb-

Re: Reg Ex to find IP address in range
by Kanji (Parson) on Aug 28, 2003 at 16:46 UTC
    /\A 111 [.] 255 [.] ( \d | [1234]\d | 5[012345] ) [.] ( \d | [1234]\d | 5[012345] ) \z/x;

    ...should work ( with /x modifier used to enhance readability ), but if you're not limited to a regexp, a cleaner ( and more easily reusable!) solution would be something like...

    return 1 if /\A 111 [.] 255 [.] (\d+) [.] (\d+) \z/x && $1 <= 55 && $2 <= 55;

        --k.


    Update: Fixed typo; thanks CS!

      Errrm... Concerning your RegEx: What about '111.255.11.11'? Should be a valid IP, but is not recognized by your pattern. Probably just a typo, change [234] to [1234]. ;-)
      Cheers, CombatSquirrel.
      Entropy is the tendency of everything going to hell.
Re: Reg Ex to find IP address in range
by NetWallah (Canon) on Aug 28, 2003 at 19:42 UTC
    I recommend using NetAddr::IP to make your life much easier, and your code more readable.

    from the docs:

    use NetAddr::IP; my $ip = new NetAddr::IP 'loopback'; if ($ip->within(new NetAddr::IP "127.0.0.0", "255.0.0.0")) { print "Is a loopback address\n"; }
    The module also has many other functions for defining and scanning subnets.
Re: Reg Ex to find IP address in range
by Aristotle (Chancellor) on Aug 28, 2003 at 17:50 UTC
    The trick is to think of sequences of digits, not the number they represent. What options exist for the first digit encountered? What conditions have to be met after a certain one of them?
    use strict; use Test::More 'no_plan'; my $rx = qr/\A (?: [0-4]\d? | 5?[0-5] ) \. (?: [0-4]\d? | 5?[0-5] ) \z/x; my %test = ( '56.0' => 0, '0.56' => 0, '48.56' => 0, '56.10' => 0, '55.0' => 1, '55.55' => 1, '0.0' => 1, '10.10' => 1, ); my $result; is(/$rx/, !!$result, $_) while ($_, $result) = each %test; __END__ ok 1 - 0.56 ok 2 - 56.10 ok 3 - 55.0 ok 4 - 55.55 ok 5 - 48.56 ok 6 - 56.0 ok 7 - 10.10 ok 8 - 0.0 1..8

    If the first digit seen is any of 0 to 4, then it is legal, and may optionally be followed by any other digit. If it is 5, it is legal, and may optionally be followed by another digit from the 0-5 range. Any other sequence is illegal.

    Update: I knew I was missing something when I wrote my test cases.. sigh. And it is so obvious. So there's a third case if the first digit is 6-9: it it is legal if not followed by anything.

    my $rx = qr/\A (?: [0-4]\d? | 5?[0-5] | [6-9] ) \. (?: [0-4]\d? | 5?[0-5] | [6-9] ) \z/x;
    Adding some cases to the test:
    '62.6' => 0, '9.97' => 0, '55.9' => 1, '1.49' => 1, '6.7' => 1, '06.7' => 1,
    They all pass. Now let's hope I'm not still a bonehead.

    Makeshifts last the longest.

      Your regex fails on for instance "7.8".

      Abigail

Re: Reg Ex to find IP address in range
by stew (Scribe) on Aug 28, 2003 at 16:32 UTC
    Of course.. I'm of to RTFM - Simplicity by Edward DeBono.

    Thanks a lot - problem solved
Re: Reg Ex to find IP address in range
by bsb (Priest) on Aug 30, 2003 at 14:27 UTC
    I'm right in the middle of Mastering Regular Expressions and he has lots of pretty pictures of how to carve up the lexical domain of strings to permit all and only the right types of numbers. He has IPs, dates and times. Using regexes for these things seems strange and error prone (eg. there was recently a bug in FormBuilder's date regex).

    Anyway, here's one the treats the digits as a number. I don't think this is a good solution in this case, but it does escape the lexical prison.

    my $rx = qr/\A (\d+) (?(?{ $1>=0 && $1<=55 }) | (?!)) \. (\d+) (?(?{ $2>=0 && $2<=55 }) | (?!)) \z/x;

Log In?
Username:
Password:

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

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

    No recent polls found