如何使用正则表达式抓取IP:PORT?

12

我正在使用PHP编写一个小型IP:PORT抓取器。问题是我对正则表达式不太熟悉。

所以我一直在拼凑我所能找到的内容。

这就是我得到的代码: /\b(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?):([0-9]{1,5})\b/

我知道这并不是最好的方法,至少不是用于获取端口号的最佳方法,因为它允许像99999这样的端口号。

此外,它似乎会返回两个匹配项。IP:PORT和PORT。我只需要它捕获完整的IP:PORT,而不是其中一个。


输入字符串的样子是什么?也就是说,你实际上是从哪里获取它们的? - DaveRandom
@DaveRandom,各种网页,其中HTML差异很大。 - Rob
你是想从完整的URL(例如http://IP:PORT/some/stuff)中提取它们吗?还是它们只是单独的IP:PORT?此外,这些地址中是否总会有:PORT部分,或者有些可能只是IP - DaveRandom
它们通常是单独存在的,但可能会有一些HTML直接在前面或后面。通常不是完整的URL,但也有可能。总是有一个:PORT部分。 - Rob
你可以尝试这个:http://stackoverflow.com/a/25866412/3767784 - FaNaJ
显示剩余2条评论
6个回答

5

我在下面发布了一个正则表达式,可以匹配IP地址或IP地址和端口。

$ip = '111.222.333.444';
if ( preg_match('/([0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3})\:?([0-9]{1,5})?/', $ip, $match) ) {
   echo 'ip: ' . $match['1'] . (isset($match['2']) ? ' port: ' . $match['2'] : '');
}

5
您的正则表达式没问题,我将专注于端口本身。这个正则表达式:
(?::                #Match the :
  (?![7-9]\d\d\d\d) #Ignrore anything above 7....
  (?!6[6-9]\d\d\d)  #Ignore anything abovr 69...
  (?!65[6-9]\d\d)   #etc...
  (?!655[4-9]\d)
  (?!6553[6-9])
  (?!0+)            #ignore complete 0(s)
  (?<Port>\d{1,5})
)?

可选择捕获任何有效的端口号并将其存储到命名组"port"中。

注意: 必须启用自由间距(free spacing):

if (preg_match(
    '/\b(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)
    (?::
      (?![7-9]\d\d\d\d) #Ignrore anything above 7....
      (?!6[6-9]\d\d\d)  #Ignore anything abovr 69...
      (?!65[6-9]\d\d)   #etc...
      (?!655[4-9]\d)
      (?!6553[6-9])
      (?!0+)            #ignore complete 0(s)
      (?P<Port>\d{1,5})
    )?
    \b/x', 
    $subject)) {
    # Successful match
}

我怎样才能确定自由间距已启用? - Rob
在正则表达式的结尾加上@Rob /x。 - FailedDev

4
你可以尝试这个:
\b(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?):\d{1,5}\b

这里有一些 IP 匹配的例子,可以在 这里 找到。只需选择其中任意一个,并在末尾添加 :\d{1,5}\b(用于匹配端口)。

是的,但这样不会匹配99999这样的端口吗? - Rob
正则表达式并不完全支持图灵完备性(Turing completeness)。你可以使用一些 PHP 来找出端口是否完全合法,或者如果愿意的话,可以将所有数字范围都放进去。编辑:有关端口,请参见 Fallen 的解决方案。我仍建议在 PHP 中完成该部分。 - Brigand

1
FailedDev的回答中有关端口部分 - 我将其缩短并设置了边界,这只会捕获端口。
\b(?![7-9]\d{4})(?!6[6-9]\d{3})(?!65[6-9]\d{2})(?!655[4-9]\d)(?!6553[6-9])(?!0+)(\d{1,5})\b

0

尝试使用此模式/正则表达式,它适用于所有情况,它会给出仅有效的IPV4格式IP地址和端口号的输出 ''^([0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}:[0-9]{1,4})(:[0-9]{1,4})?$'

我的输入:

10.128.16.38:22

1050:0000:0000:0000:0005:0600:300c:326b:22

11.11.11.11

asdfasdf

1012312101231210123121012312101231210123121012312101231210123121012312

这是与编程相关的文本。

10.128.45.23:9095

10.128.16.27:22 asdfasdfasdf

as@#$@#$

1050:0000:0000:0000:0005:0600:3002:3260:90

10.128.16.27:22 asdfasdfasdf

as@#$@#$

1050:0000:0000:0000:0005:0600:3002:3260:90

10.128.46.00:

输出:(仅有效的IP:端口):

10.128.16.38:22

10.128.45.23:9095


0

我很久以前用过这个。

[0-9]{3}.[0-9]{3}.[0-9]{3}.[0-9]{3}:[0-9]{5}

2
为什么要使用[0-9]?我无法想象一个IP地址是999.999.999.999或者接近这个数值。目前来看,我在问题中提供的那个更加高效。 - Rob

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接