检查字符串是否在PHP中包含IPv6地址



使用PHP,我需要检查字符串是否包含IPv6地址 - 然后提取该IPv6地址(如果可以)。

,如果完全是IPv6:

,我有一个正则符合字符串
$matches = [];
$regex = '/^(((?=.*(::))(?!.*3.+3))3?|([dA-F]{1,4}(3|:b|$)|2))(?4){5}((?4){2}|(((2[0-4]|1d|[1-9])?d|25[0-5]).?b){4})z/i';
preg_match($regex, $ipv6, $matches);

我坚持的是能够在任一侧添加通配符,因此我可以匹配以下内容:

  • http://2001:0db8:85a3:0000:0000:8A2E:0370:7334/sosings/page.html
  • http://2001:0db8:85a3:0000:0000:8A2E:0370:7334
  • 2001:0db8:85a3:0000:0000:8A2E:0370:7334/sosings/page.html

最终我需要这样做,以便我可以围绕IPv6地址包裹方括号,因此它符合RFC 3986(例如http://[2001:0db8:85a3:0000:0000:8a2e:0370:7334]/something/page.html)。

您不需要读取和理解regex即可验证字符串是否是有效的IPv6地址。php功能filter_var()可以为您忙碌:

echo(filter_var('2001:0db8:85a3:0000:0000:8a2e:0370:7334', FILTER_VALIDATE_IP));
# 2001:0db8:85a3:0000:0000:8a2e:0370:7334
echo(filter_var('2001:0db8:85a3::8a2e:0370:7334', FILTER_VALIDATE_IP));
# 2001:0db8:85a3::8a2e:0370:7334
echo(filter_var('192.168.0.1', FILTER_VALIDATE_IP));
# 192.168.0.1
var_dump(filter_var('192.168.0.1', FILTER_VALIDATE_IP, FILTER_FLAG_IPV6));
# bool(false)

如果其有效,它将返回输入值(根据第二个参数传递的过滤器,并以第三个参数传递的选项)或否则为false。

如果IP地址是URL的域,则可以使用PHP函数parse_url()提取:

print_r(parse_url('http://2001:0db8:85a3:0000:0000:8a2e:0370:7334/something/page.html'));
# Array
# (
#     [scheme] => http
#     [host] => 2001:0db8:85a3:0000:0000:8a2e:0370:7334
#     [path] => /something/page.html
# )

示例中的最后一个字符串(2001:0db8:85a3:0000:0000:8a2e:0370:7334/something/page.html)不是URL。这只是一些随机文本,看起来像是一个不完整(无效的)URL。我没有简单的解决方案: - (

您需要使用另一个正格书:

(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|::(ffff(:0{1,4}){0,1}:){0,1}((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]).){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])|([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]).){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]))

之后,您可以在链接中包装IPv6:

<?php
$ipv6 = 'http://2001:0db8:85a3:0000:0000:8a2e:0370:7334/something/page.html';
$matches = [];
$regex = '(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|::(ffff(:0{1,4}){0,1}:){0,1}((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]).){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])|([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]).){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]))';
if (preg_match($regex, $ipv6, $matches)) {
    $result = str_replace($matches[0], '[' .  $matches[0] . ']', $ipv6);
}

也许2条正则匹配对此会更好。因为您的正则是复杂的

$regex1 = '/^https?://([a-z0-9:]{39})/';
if( preg_match( $regex1, $your_text, $matches1) ) {
    $regex2 = '/[a-z0-9]{4}:?/';
    if( preg_match_all( $regex2, $matches1[1], $matches2 ) === 8 )
        echo $your_text.' qualifies!!'; 
}

简介

我尚未完全测试代码,所以我不能100%确定它有效,但是,我会根据一些不同的URL运行它,并且似乎正常工作。

我采取了这些答案的一部分:

  • 希望构建一些正则验证域名(RFC 952/RFC 1123)
  • 什么是RFC同同性恋和正则表达式以检查字符串是否为有效的URL
  • 与有效IPv6地址匹配的正则表达式

答案

用域名回答

这就是我想到的:

(?(DEFINE)
  (?<scheme>[a-z][a-z0-9+.-]*)
  (?<userpass>([^:@/](:[^:@/])?@))
  (?<domain>[a-z0-9]+(-[a-z0-9]+)*(.[a-z0-9]+(-[a-z0-9]+)*)+)
  (?<ip>(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|::(ffff(:0{1,4}){0,1}:){0,1}((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]).){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])|([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]).){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])))
  (?<host>((?&domain)|(?&ip)))
  (?<port>(:[d]{1,5}))
  (?<path>([^?;#]*))
  (?<query>(?[^#;]*))
  (?<anchor>(#.*))
)
^(?:(?&scheme)://)?(?&userpass)?(?<address>(?&host))(?&port)?/?(?&path)?(?&query)?(?&anchor)?$

请按照此链接在使用中查看

没有域名的答案

上面的正则态度将匹配包含有效域的URL(无论是域名还是地址)。如果要匹配 IP地址,请使用以下正则(在名为host的定义组中包含一个简单的更改) - 我删除了对名为domain的定义组的引用)

(?(DEFINE)
  (?<scheme>[a-z][a-z0-9+.-]*)
  (?<userpass>([^:@/](:[^:@/])?@))
  (?<domain>[a-z0-9]+(-[a-z0-9]+)*(.[a-z0-9]+(-[a-z0-9]+)*)+)
  (?<ip>(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|::(ffff(:0{1,4}){0,1}:){0,1}((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]).){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])|([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]).){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])))
  (?<host>(?&ip))
  (?<port>(:[d]{1,5}))
  (?<path>([^?;#]*))
  (?<query>(?[^#;]*))
  (?<anchor>(#.*))
)
^(?:(?&scheme)://)?(?&userpass)?(?<address>(?&host))(?&port)?/?(?&path)?(?&query)?(?&anchor)?$

请按照此链接在使用中查看

对于那些喜欢一个不错的不符号查询的人来说

^(?:[a-z][a-z0-9+.-]*://)?(?:[^:@/](?::[^:@/])?@)?(?<address>(?:[0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|(?:[0-9a-fA-F]{1,4}:){1,7}:|(?:[0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|(?:[0-9a-fA-F]{1,4}:){1,5}(?::[0-9a-fA-F]{1,4}){1,2}|(?:[0-9a-fA-F]{1,4}:){1,4}(?::[0-9a-fA-F]{1,4}){1,3}|(?:[0-9a-fA-F]{1,4}:){1,3}(?::[0-9a-fA-F]{1,4}){1,4}|(?:[0-9a-fA-F]{1,4}:){1,2}(?::[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:(?:(?::[0-9a-fA-F]{1,4}){1,6})|:(?:(?::[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(?::[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|::(?:ffff(?::0{1,4}){0,1}:){0,1}(?:(?:25[0-5]|(?:2[0-4]|1{0,1}[0-9]){0,1}[0-9]).){3,3}(?:25[0-5]|(?:2[0-4]|1{0,1}[0-9]){0,1}[0-9])|(?:[0-9a-fA-F]{1,4}:){1,4}:(?:(?:25[0-5]|(?:2[0-4]|1{0,1}[0-9]){0,1}[0-9]).){3,3}(?:25[0-5]|(?:2[0-4]|1{0,1}[0-9]){0,1}[0-9]))(?::[d]{1,5})?/?(?:[^?;#]*)?(?:?[^#;]*)?(?:#.*)?$

注意:这两个答案均使用i(情况不敏感)和x(忽略Whitespace)修饰符

最新更新