Reputation: 43
this is my first question so please be nice :). I'm trying to build a regexp to get an array of IPs that are both valid (OK, at least with the proper IPv4 format) and NOT a private IP according to RFC 1918. So far, I've figured out a way to get exactly the opposite, I mean succcssfuly matching private IPs, so all what I need is a way to revert the assertion. This is the code so far:
// This is an example string
$ips = '10.0.1.23, 192.168.1.2, 172.24.2.189, 200.52.85.20, 200.44.85.20';
preg_match_all('/(?:10\.\d{1,3}|172\.(?:1[6-9]|2\d|3[01])|192\.168)\.\d{1,3}\.\d{1,3}/', $ips, $matches);
print_r($matches);
// Prints:
Array
(
[0] => Array
(
[0] => 10.0.1.23
[1] => 192.168.1.2
[2] => 172.24.2.189
)
)
And what I want as result is:
Array
(
[0] => Array
(
[0] => 200.52.85.20
[1] => 200.44.85.20
)
)
I've tried changing the first part of the expression (the lookahead) to be negative (?!) but this messes up the results and don't even switch the result.
If you need any more informartion please feel free to ask, many thanks in advance.
Upvotes: 4
Views: 234
Reputation:
If all you want to do is to exclude a relatively small range of ip's, you could do this (if I didn't make any typo's):
/(?!\b(?:10\.\d{1,3}|172\.(?:1[6-9]|2\d|3[01])|192\.168)\.\d{1,3}\.\d{1,3}\b)\b(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\b)/
Example in Perl:
use strict;
use warnings;
my @found = '10.0.1.23, 192.168.1.2, 172.24.2.189, 200.52.85.20, 200.44.85.20' =~
/
(?!
\b
(?:
10\.\d{1,3}
|
172\.
(?:
1[6-9]
| 2\d
| 3[01]
)
|
192\.168
)
\.\d{1,3}
\.\d{1,3}
\b
)
\b(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\b)
/xg;
for (@found) {
print "$_\n";
}
Output:
200.52.85.20
200.44.85.20
Upvotes: 0
Reputation: 25060
There is a PHP function for that: filter_var(). Check these constants: FILTER_FLAG_IPV4
, FILTER_FLAG_NO_PRIV_RANGE
.
However if you still want to solve this with regular expressions, I suggest you split your problem in two parts: first you extract all the IP addresses, then you filter out the private ones.
Upvotes: 4