PHP RegEx还原断言以获得相反的匹配

时间:2011-06-24 19:30:43

标签: php regex

这是我的第一个问题所以请你好:)。我正在尝试构建一个正则表达式,以获得有效的IP数组(确定,至少使用正确的IPv4格式),而不是根据RFC 1918的私有IP。到目前为止,我已经找到了一种方法完全相反,我的意思是succcssfuly匹配私有IP,所以我需要的是一种方法来恢复断言。这是到目前为止的代码:

// 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
  )
)

我想要的结果是:

Array
(
  [0] => Array
  (
    [0] => 200.52.85.20
    [1] => 200.44.85.20
  )
)

我已经尝试将表达式的第一部分(前瞻)更改为否定(?!)但这会弄乱结果,甚至不会切换结果。

如果您需要更多信息,请随时提出,非常感谢。

2 个答案:

答案 0 :(得分:4)

有一个PHP函数:filter_var()。请检查以下常量:FILTER_FLAG_IPV4FILTER_FLAG_NO_PRIV_RANGE

但是,如果你仍然想用正则表达式来解决这个问题,我建议你将问题分成两部分:首先提取所有IP地址,然后过滤掉私有地址。

答案 1 :(得分:0)

如果您只想排除相对较小范围的ip,那么您可以这样做 (如果我没有做任何错字):

/(?!\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)/

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";
}

输出:

200.52.85.20
200.44.85.20