关于正则表达式:匹配有效IPv6地址的正则表达式

您所在的位置:网站首页 ipv6缩写规范 关于正则表达式:匹配有效IPv6地址的正则表达式

关于正则表达式:匹配有效IPv6地址的正则表达式

2024-06-25 00:58| 来源: 网络整理| 查看: 265

我在编写匹配有效IPv6地址的正则表达式时遇到了麻烦,包括压缩格式的地址(每个字节对均省略了::或前导零)。

有人可以建议一个满足要求的正则表达式吗?

我正在考虑扩展每个字节对,并将结果与一个更简单的正则表达式匹配。

相关讨论 查看intermapper.com/ipv6validator ..它链接到此perl测试脚本 我已经尝试了以下所有答案,但它们不适用于我的所有测试用例,并且/或者它们还包含未要求的IPv4。 我发现到目前为止,这是最干净的解决方案:stackoverflow.com/a/21944928/3112803

我无法获得@Factor Mystic的答案才能使用POSIX正则表达式,因此我编写了一个可用于POSIX正则表达式和PERL正则表达式的答案。

它应该匹配:

IPv6地址 零压缩IPv6地址(rfc5952的2.2节) 具有区域索引的链接本地IPv6地址(rfc4007的第11节) IPv4嵌入式IPv6地址(rfc6052的第2部分) IPv4映射的IPv6地址(rfc2765的2.1节) IPv4转换的地址(rfc2765的2.1节)

IPv6正则表达式:

1(([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]))

为了便于阅读,以下是上述正则表达式,将其在主要OR点处分为几行:

12345678910111213141516171819202122# IPv6 RegEx ( ([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|          # 1:2:3:4:5:6:7:8 ([0-9a-fA-F]{1,4}:){1,7}:|                         # 1::                              1:2:3:4:5:6:7:: ([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|         # 1::8             1:2:3:4:5:6::8  1:2:3:4:5:6::8 ([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|  # 1::7:8           1:2:3:4:5::7:8  1:2:3:4:5::8 ([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|  # 1::6:7:8         1:2:3:4::6:7:8  1:2:3:4::8 ([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|  # 1::5:6:7:8       1:2:3::5:6:7:8  1:2:3::8 ([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|  # 1::4:5:6:7:8     1:2::4:5:6:7:8  1:2::8 [0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|       # 1::3:4:5:6:7:8   1::3:4:5:6:7:8  1::8   :((:[0-9a-fA-F]{1,4}){1,7}|:)|                     # ::2:3:4:5:6:7:8  ::2:3:4:5:6:7:8 ::8       ::     fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|     # fe80::7:8%eth0   fe80::7:8%1     (link-local IPv6 addresses with zone index) ::(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])|          # ::255.255.255.255   ::ffff:255.255.255.255  ::ffff:0:255.255.255.255  (IPv4-mapped IPv6 addresses and IPv4-translated addresses) ([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])           # 2001:db8:3:4::192.0.2.33  64:ff9b::192.0.2.33 (IPv4-Embedded IPv6 Address) ) # IPv4 RegEx ((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])

为了使上面的内容更容易理解,下面的"伪"代码复制了上面的内容:

1234567891011121314151617IPV4SEG  = (25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]) IPV4ADDR = (IPV4SEG\.){3,3}IPV4SEG IPV6SEG  = [0-9a-fA-F]{1,4} IPV6ADDR = (            (IPV6SEG:){7,7}IPV6SEG|                # 1:2:3:4:5:6:7:8            (IPV6SEG:){1,7}:|                      # 1::                                 1:2:3:4:5:6:7::            (IPV6SEG:){1,6}:IPV6SEG|               # 1::8               1:2:3:4:5:6::8   1:2:3:4:5:6::8            (IPV6SEG:){1,5}(:IPV6SEG){1,2}|        # 1::7:8             1:2:3:4:5::7:8   1:2:3:4:5::8            (IPV6SEG:){1,4}(:IPV6SEG){1,3}|        # 1::6:7:8           1:2:3:4::6:7:8   1:2:3:4::8            (IPV6SEG:){1,3}(:IPV6SEG){1,4}|        # 1::5:6:7:8         1:2:3::5:6:7:8   1:2:3::8            (IPV6SEG:){1,2}(:IPV6SEG){1,5}|        # 1::4:5:6:7:8       1:2::4:5:6:7:8   1:2::8            IPV6SEG:((:IPV6SEG){1,6})|             # 1::3:4:5:6:7:8     1::3:4:5:6:7:8   1::8            :((:IPV6SEG){1,7}|:)|                  # ::2:3:4:5:6:7:8    ::2:3:4:5:6:7:8  ::8       ::                  fe80:(:IPV6SEG){0,4}%[0-9a-zA-Z]{1,}|  # fe80::7:8%eth0     fe80::7:8%1  (link-local IPv6 addresses with zone index)            ::(ffff(:0{1,4}){0,1}:){0,1}IPV4ADDR|  # ::255.255.255.255  ::ffff:255.255.255.255  ::ffff:0:255.255.255.255 (IPv4-mapped IPv6 addresses and IPv4-translated addresses)            (IPV6SEG:){1,4}:IPV4ADDR               # 2001:db8:3:4::192.0.2.33  64:ff9b::192.0.2.33 (IPv4-Embedded IPv6 Address)            )

我在GitHub上发布了一个脚本来测试正则表达式:https://gist.github.com/syzdek/6086792

相关讨论 反应出色。我只希望RegexPlanet现在可以工作(以某种方式不能让我建立共享链接),因为Ive制作了非捕获变体,并且我将所有示例添加为测试。 为什么在ip4模式中的.前面使用转义,而在ip6模式中的.是未转义的呢?这是故意的吗? +1。看起来作者忘记了逃避. 您的IPv4正则表达式与127.000.000.001之类的IP不匹配 IPv4段不应包含前导零。如果存在前导零,则应将IPv4段解释为八进制。因此,上面的IPV4SEG不允许000正确。但是它允许00,但不允许。 不能像我期望的那样在浏览器中为我工作。甚至验证了reg.test(3zzzzffe:1900:4545:3:200:f8ff:fe21:67cf)显然也不是有效的IPv6地址。使用regex在这里有更好的结果:nbviewer.ipython.org/github/rasbt/python_reference/blob/master/ 据我所知,匹配不是有效IP地址的" :: _"。 梦幻般的ipv6正则表达式。在链接本地部分中发现了一个小错误。您有fe80,其中应该是[fF][eE]80,而ffff应该是[fF]{4} 您在映射的ipv4中有误,应该使用双冒号,例如(([[0-9a-fA-F] {1,4}:){1,4}:)([[0-9a-fA-F] {1, 4} :) IPv4regex 对于带有前导零的IPv4匹配,可以使用:(25 [0-5] | 2 [0-4] d | [0-1]? d? d)(。(25 [0-5] | 2 [0-4] d | [0-1]? d? d)){3} Aria的问题stackoverflow.com/questions/32368008/包含对最后评论的答案。 +1表示如果小心并格式化正则表达式可以(与任何源代码相同)实际可读。 虽然如果知道要查找的内容,则编写正则表达式模式并不重要,但这是一个平凡且容易出错的任务。非常感谢您抽出宝贵的时间以正确的方式进行此操作,并通过有用的注释将其分解! 它对我不起作用:$ [["" 2001:bobbydavro :: 1" =?$ RE_IPV6]] && echo"是" ||回声"不"是 我将其放入Python RE形式:gist.github.com/dfee/6ed3a4b05cfe7a6faf40a2102408d5d8 测试用例失败:fe80 :: 0202:B3FF:FE1E:8329 由于某些平台的延迟出口会导致意外的延迟匹配,从而忽略了地址的最后一段。要解决此问题,您必须将(IPV6SEG:){7,7}:移动到其他压缩匹配项之后,并反转压缩匹配项的顺序。 (请参阅stackoverflow.com/a/14453696/4151626) ...(续)...首先移动fe80规则,最后移动:((:IPV6SEG){1,7}规则,然后再移动::(ffff规则(倒数第二)。 (IPV6SEG:){7,7}:是倒数第三。 ...(续)...将(IPV6SEG:){1,4}:IPV4ADDR规则移到(IPV6SEG:){1,4}(:IPVSEG){1,3}规则之前。 最后,...由于未知原因,在我的平台上,我不得不将IPV4SEG更改为(25[0-5]|2[0-4][0-9]|1{0,1}[0-9]{0,1}[0-9])或更严格的(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]{0,1}[0-9]),以避免将09和08解释为非法八进制。 我偶然发现了一种错误通过的表格:" 2。81fa:a3c:206e:334e:b77f ::" 不起作用。 regextester.com/?fam=104498 @ergohack,您可以发布可使用的Regex解决方案来处理延迟退出吗? 不幸的是,@ OwN太长了78个字符,因此无法发布为该封闭线程的替代答案,...我将在后续评论中发布它,请仔细将它们缝合在一起:(fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}: @OwN-第2部分:|([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|2[0-4][0-9]|1{0,1}[0-9]{0,1}[0-9])\.{3,3})(25[0-5]|2[0-4][0-9]|1{0,1}[0-9]{0,1}[0-9])|::(ffff(:0{1,4}){0,1}:){0,1}((25[0-5]|2[0-4][0-9]|1{0,1}[0-9]{0,1}[0-9])\.{3,3})(25[0-5]|2[0-4][0-9]|1{0,1}[0-9]{0,1}[0-9])|:((:[0-9a-fA-F]{1,4}){1,7}|:))

以下内容将验证IPv4,IPv6(完整和压缩)和IPv6v4(完整和压缩)地址:

1'/^(?>(?>([a-f0-9]{1,4})(?>:(?1)){7}|(?!(?:.*[a-f0-9](?>:|$)){8,})((?1)(?>:(?1)){0,6})?::(?2)?)|(?>(?>(?1)(?>:(?1)){5}:|(?!(?:.*[a-f0-9]:){6,})(?3)?::(?>((?1)(?>:(?1)){0,4}):)?)?(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])(?>\.(?4)){3}))$/iD' 相关讨论 即使可以按照Frank Krueger的建议完成ip-s验证,该解决方案还是可以实际回答问题的方法(尽管我尚未对其进行全面测试),并且您是否有许多要进行语法测试的IP-s,也许如果要在一行文本中匹配,则不能使用IP验证技术。 嗨,我测试了此RegExp,但没有为我工作。它说D是一个无效的标志,当我删除它时它说" SyntaxError:无效的量词" 您正在使用什么软件?这适用于PCRE,但不适用于Perl。 前端javascript。这是我使用的代码var pattern = PATTERN; return [pattern.test(value), The Address entered is invalid.]; JavaScript实现了Perl样式的正则表达式的子集,而不是PCRE的全部。没有PCRE的某些高级功能,我的正则表达式将无法工作。 这为我在C#中提供了例外 C#是否使用PCRE? 测试用例失败:FE80:0000:0000:0000:0202:B3FF:FE1E:8329在此日期使用最新版本的Elixir,其下面使用PCRE。 C#不支持原子分组(例如(?>)。 此形式不适用于ipv6的所有可能形式

来自" IPv6正则表达式":

1234567891011121314151617(\A([0-9a-f]{1,4}:){1,1}(:[0-9a-f]{1,4}){1,6}\Z)| (\A([0-9a-f]{1,4}:){1,2}(:[0-9a-f]{1,4}){1,5}\Z)| (\A([0-9a-f]{1,4}:){1,3}(:[0-9a-f]{1,4}){1,4}\Z)| (\A([0-9a-f]{1,4}:){1,4}(:[0-9a-f]{1,4}){1,3}\Z)| (\A([0-9a-f]{1,4}:){1,5}(:[0-9a-f]{1,4}){1,2}\Z)| (\A([0-9a-f]{1,4}:){1,6}(:[0-9a-f]{1,4}){1,1}\Z)| (\A(([0-9a-f]{1,4}:){1,7}|:):\Z)| (\A:(:[0-9a-f]{1,4}){1,7}\Z)| (\A((([0-9a-f]{1,4}:){6})(25[0-5]|2[0-4]\d|[0-1]?\d?\d)(\.(25[0-5]|2[0-4]\d|[0-1]?\d?\d)){3})\Z)| (\A(([0-9a-f]{1,4}:){5}[0-9a-f]{1,4}:(25[0-5]|2[0-4]\d|[0-1]?\d?\d)(\.(25[0-5]|2[0-4]\d|[0-1]?\d?\d)){3})\Z)| (\A([0-9a-f]{1,4}:){5}:[0-9a-f]{1,4}:(25[0-5]|2[0-4]\d|[0-1]?\d?\d)(\.(25[0-5]|2[0-4]\d|[0-1]?\d?\d)){3}\Z)| (\A([0-9a-f]{1,4}:){1,1}(:[0-9a-f]{1,4}){1,4}:(25[0-5]|2[0-4]\d|[0-1]?\d?\d)(\.(25[0-5]|2[0-4]\d|[0-1]?\d?\d)){3}\Z)| (\A([0-9a-f]{1,4}:){1,2}(:[0-9a-f]{1,4}){1,3}:(25[0-5]|2[0-4]\d|[0-1]?\d?\d)(\.(25[0-5]|2[0-4]\d|[0-1]?\d?\d)){3}\Z)| (\A([0-9a-f]{1,4}:){1,3}(:[0-9a-f]{1,4}){1,2}:(25[0-5]|2[0-4]\d|[0-1]?\d?\d)(\.(25[0-5]|2[0-4]\d|[0-1]?\d?\d)){3}\Z)| (\A([0-9a-f]{1,4}:){1,4}(:[0-9a-f]{1,4}){1,1}:(25[0-5]|2[0-4]\d|[0-1]?\d?\d)(\.(25[0-5]|2[0-4]\d|[0-1]?\d?\d)){3}\Z)| (\A(([0-9a-f]{1,4}:){1,5}|:):(25[0-5]|2[0-4]\d|[0-1]?\d?\d)(\.(25[0-5]|2[0-4]\d|[0-1]?\d?\d)){3}\Z)| (\A:(:[0-9a-f]{1,4}){1,5}:(25[0-5]|2[0-4]\d|[0-1]?\d?\d)(\.(25[0-5]|2[0-4]\d|[0-1]?\d?\d)){3}\Z) 相关讨论 这样的正则表达式应该是一种"代码味道",也许正则表达式不是此处的最佳选择。 (尽管如此,我想操作人员确实要求它...) @Thanatos谁在乎它是否有效? @ user712092-每个看到过类似代码的人的人 港口呢? 这对RE来说是完全不必要的麻烦。生成它的程序不了解它在做什么。人类永远不会这样做。不要被表面上的复杂性所迷惑-可再生能源对许多人来说确实是"黑魔法",但是没有理由将它们放置在另一个星球上! +1,但O.M.G.有一种更好的方法可以做到这一点:P作为参考:对于Rails,这可能会有所帮助:stackoverflow.com/questions/16965697/ 确实是一种代码气味。但是,看一看后,您会发现每个正则表达式都非常简洁。问题是ipv6压缩产生了不同的模式-冒号的开头,中间和结尾,如果您使用了双冒号,那么您就不能再使用它,而在双精度前后的总冒号之上必须加起来。 Perl 6也许可以解决这个问题,但这远远超出了PCRE语法。 (PS-我不算最后的嵌入式ipv4,它比ipv6部分长!)

听起来您可能正在使用Python。如果是这样,您可以使用以下方法:

12345678910111213import socket def check_ipv6(n):     try:         socket.inet_pton(socket.AF_INET6, n)         return True     except socket.error:         return False print check_ipv6('::1') # True print check_ipv6('foo') # False print check_ipv6(5)     # TypeError exception print check_ipv6(None)  # TypeError exception

我认为您不必将IPv6编译到Python中即可获得inet_pton,如果您将socket.AF_INET作为第一个参数传递,它也可以解析IPv4地址。注意:这可能不适用于非Unix系统。

相关讨论 您应该在except子句中指定异常类型。否则,except将捕获所有内容,并可能掩盖不相关的错误。此处的类型应为socket.error。 A)inet_pton不会抛出其他异常,除非文档是错误的;以及B)即使发生了异常,您还会返回什么,但假的呢? 回复:其他错误...如果用户传入非字符串,则会误食TypeError。显然,列表不是ipv6,但Id可能希望我输入错误的类型。 +1这对我很有帮助。还应该添加几个附加点:1)socket.inet_pton可用于测试两个IP地址家族(IP和IPv6)的有效性。 2)此处的文档(docs.python.org/2/library/socket.html)建议在Unix平台上可用。它可能在Win平台上不可用。 使用Django,这会有所帮助!

我必须坚决支持弗兰克·克鲁格的回答。

虽然您说您需要一个正则表达式来匹配IPv6地址,但我假设您真正需要的是能够检查给定的字符串是否为有效的IPv6地址。这里有一个微妙但重要的区别。

有多种方法可以检查给定字符串是否为有效的IPv6地址,而正则表达式匹配只是一种解决方案。

如果可以,请使用现有的库。该库将具有较少的错误,并且其使用将减少需要维护的代码。

Factor Mystic建议的正则表达式长而复杂。它很可能有效,但是您还应该考虑如果意外失败,应该如何应对。我要在此处说明的要点是,如果您自己无法形成所需的正则表达式,则将无法轻松调试它。

如果没有合适的库,最好编写自己的不依赖于正则表达式的IPv6验证例程。如果您编写它,则说明您理解它;如果您理解,则可以添加注释以对其进行解释,以便其他人也可以理解并随后对其进行维护。

使用正则表达式时,请谨慎行事,而您无法向他人解释其功能。

相关讨论 使用两个正则表达式,一个自由表达式和一个异常表达式来捕获第一个表达式允许的无效地址,可能比一个表达式(return ex1.match(S) && ! ex2.match(S))更容易。 您假设他几乎肯定会在大量文本中搜索IP时正在验证单个IP。

我不是Ipv6专家,但我认为您可以通过以下方法更轻松地获得不错的结果:

1^([0-9A-Fa-f]{0,4}:){2,7}([0-9A-Fa-f]{1,4}$|((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)(\.|$)){4})$

回答"是有效的ipv6",对我来说似乎还可以。要将它分解成一部分...算了。我省略了未指定的(::),因为在我的数据库中没有"未指定的地址"。

开始: ^([0-9A-Fa-f]{0,4}:){2,7}

其次是: [0-9A-Fa-f]{1,4}$ ((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)(\.|$)){4}

相关讨论 +1表示实际上坚持OP的问题,并提出了一个相对有效的正则表达式,该方法有些起作用。 这不匹配" :: 1" ??在Java正则表达式语法中,它确实匹配:start() = 0, end() = 3 group(0) ="::1" group(1) =":" group(2) ="1" group(3) ="null" group(4) ="null" group(5) ="null" 有人通知我我的正则表达式有问题,压缩的部分" ::"只能出现一次。因此," :: 1 :: 2"将与我的正则表达式匹配,但它不是有效的IPV6。第二个正则表达式可以验证这种情况。完整的建议是使用状态分析器进行验证。我同意,生成的代码将更易于阅读和维护(并且可能有人已经在某个地方的开放源代码中对其进行了编码)。

这个正则表达式将根据GNU C ++ regex的实现与有效的IPv6和IPv4地址进行匹配,并使用REGULAR EXTENDED模式:

1"^\s*((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|((25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])(\.(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])){3})|:))|(([0-9A-Fa-f]{1,4}:){5}(((:[0-9A-Fa-f]{1,4}){1,2})|:((25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])(\.(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])){3})|:))|(([0-9A-Fa-f]{1,4}:){4}(((:[0-9A-Fa-f]{1,4}){1,3})|((:[0-9A-Fa-f]{1,4})?:((25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])(\.(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])){3}))|:))|(([0-9A-Fa-f]{1,4}:){3}(((:[0-9A-Fa-f]{1,4}){1,4})|((:[0-9A-Fa-f]{1,4}){0,2}:((25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])(\.(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])){3}))|:))|(([0-9A-Fa-f]{1,4}:){2}(((:[0-9A-Fa-f]{1,4}){1,5})|((:[0-9A-Fa-f]{1,4}){0,3}:((25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])(\.(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])){3}))|:))|(([0-9A-Fa-f]{1,4}:){1}(((:[0-9A-Fa-f]{1,4}){1,6})|((:[0-9A-Fa-f]{1,4}){0,4}:((25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])(\.(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])){3}))|:))|(:(((:[0-9A-Fa-f]{1,4}){1,7})|((:[0-9A-Fa-f]{1,4}){0,5}:((25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])(\.(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])){3}))|:)))(%.+)?\s*$"

这也捕获了loopback(:: 1)和ipv6地址。 将{}更改为+并将:放在第一个方括号内。

1([A-f0-9:]+:+)+[A-f0-9]+

使用ifconfig -a输出进行测试 http://regexr.com/

Unix或Mac OSx终端o选项仅返回匹配的输出(ipv6),包括:: 1

1ifconfig -a | egrep -o '([A-f0-9:]+:+)+[A-f0-9]+'

获取所有IP地址(IPv4或IPv6)并在Unix OSx上打印匹配项

1ifconfig -a | egrep -o '([0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}) | (([A-f0-9:]+:+)+[A-f0-9]+)' 相关讨论 我喜欢简单。最终这对我有用:ip a | grep -Po [\w:]+:+[\w:]+ 幽默感激!

谨防!在Java中,使用InetAddress和相关类(Inet4Address,Inet6Address,URL)可能会涉及网络流量!例如。 DNS解析(URL.equals,InetAddress来自字符串!)。该通话可能需要很长时间,并且阻塞了!

对于IPv6,我有类似的内容。当然,这不会处理IPv6的非常细微的细节,例如仅在某些类别的IPv6地址上允许区域索引。而且此正则表达式不是为组捕获而编写的,它只是"匹配"类型的正则表达式。

S-IPv6段= [0-9a-f]{1,4}

I-IPv4 = (?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9]{1,2})\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9]{1,2})

示意图(第一部分将IPv6地址与后缀IPv4匹配,第二部分将IPv6地址匹配,最后是区域索引):

1234567891011121314151617181920212223242526( ( ::(S:){0,5}| S::(S:){0,4}| (S:){2}:(S:){0,3}| (S:){3}:(S:){0,2}| (S:){4}:(S:)?| (S:){5}:| (S:){6} ) I | :(:|(:S){1,7})| S:(:|(:S){1,6})| (S:){2}(:|(:S){1,5})| (S:){3}(:|(:S){1,4})| (S:){4}(:|(:S){1,3})| (S:){5}(:|(:S){1,2})| (S:){6}(:|(:S))| (S:){7}:| (S:){7}S ) (?:%[0-9a-z]+)?

在这里,可能的正则表达式(不区分大小写,被行的开头/结尾等所需要的内容所包围,等等):

12345678910111213141516171819202122232425(?: (?: ::(?:[0-9a-f]{1,4}:){0,5}| [0-9a-f]{1,4}::(?:[0-9a-f]{1,4}:){0,4}| (?:[0-9a-f]{1,4}:){2}:(?:[0-9a-f]{1,4}:){0,3}| (?:[0-9a-f]{1,4}:){3}:(?:[0-9a-f]{1,4}:){0,2}| (?:[0-9a-f]{1,4}:){4}:(?:[0-9a-f]{1,4}:)?| (?:[0-9a-f]{1,4}:){5}:| (?:[0-9a-f]{1,4}:){6} ) (?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9]{1,2})\.){3} (?:25[0-5]|2[0-4][0-9]|[01]?[0-9]{1,2})| :(?::|(?::[0-9a-f]{1,4}){1,7})| [0-9a-f]{1,4}:(?::|(?::[0-9a-f]{1,4}){1,6})| (?:[0-9a-f]{1,4}:){2}(?::|(?::[0-9a-f]{1,4}){1,5})| (?:[0-9a-f]{1,4}:){3}(?::|(?::[0-9a-f]{1,4}){1,4})| (?:[0-9a-f]{1,4}:){4}(?::|(?::[0-9a-f]{1,4}){1,3})| (?:[0-9a-f]{1,4}:){5}(?::|(?::[0-9a-f]{1,4}){1,2})| (?:[0-9a-f]{1,4}:){6}(?::|(?::[0-9a-f]{1,4}))| (?:[0-9a-f]{1,4}:){7}:| (?:[0-9a-f]{1,4}:){7}[0-9a-f]{1,4} ) (?:%[0-9a-z]+)?

如果您使用Perl,请尝试使用Net :: IPv6Addr

123456use Net::IPv6Addr; if( defined Net::IPv6Addr::is_ipv6($ip_address) ){   print"Looks like an ipv6 address "; }

NetAddr :: IP

123use NetAddr::IP; my $obj = NetAddr::IP->new6($ip_address);

验证:: IP

123456use Validate::IP qw'is_ipv6'; if( is_ipv6($ip_address) ){   print"Looks like an ipv6 address "; } 相关讨论 或Data :: Validate :: IP search.cpan.org/~neely/Data-Validate-IP-0.11/lib/Data/Validate/。

一个简单的正则表达式可以匹配,但是我不建议任何形式的验证是这样的:

1([A-Fa-f0-9]{1,4}::?){1,7}[A-Fa-f0-9]{1,4}

请注意,这与地址中的任何位置的压缩匹配,尽管它与环回地址:: 1不匹配。我发现这是一个合理的折衷,以使正则表达式保持简单。

我在iTerm2智能选择规则中成功使用了它,以四击IPv6地址。

相关讨论 您的意思是A-F,而不是A-Z!另请注意,您不包括点分四进制表示法。

在Scala中,使用众所周知的Apache Commons验证器。

http://mvnrepository.com/artifact/commons-validator/commons-validator/1.4.1

123456789101112libraryDependencies +="commons-validator" %"commons-validator" %"1.4.1" import org.apache.commons.validator.routines._ /**  * Validates if the passed ip is a valid IPv4 or IPv6 address.  *  * @param ip The IP address to validate.  * @return True if the passed IP address is valid, false otherwise.  */    def ip(ip: String) = InetAddressValidator.getInstance().isValid(ip)

按照方法ip(ip: String)的测试:

1234567891011121314151617181920212223242526"The `ip` validator" should {  "return false if the IPv4 is invalid" in {     ip("123") must beFalse     ip("255.255.255.256") must beFalse     ip("127.1") must beFalse     ip("30.168.1.255.1") must beFalse     ip("-1.2.3.4") must beFalse   }  "return true if the IPv4 is valid" in {     ip("255.255.255.255") must beTrue     ip("127.0.0.1") must beTrue     ip("0.0.0.0") must beTrue   }   //IPv6   //@see: http://www.ronnutter.com/ipv6-cheatsheet-on-identifying-valid-ipv6-addresses/  "return false if the IPv6 is invalid" in {     ip("1200::AB00:1234::2552:7777:1313") must beFalse   }  "return true if the IPv6 is valid" in {     ip("1200:0000:AB00:1234:0000:2552:7777:1313") must beTrue     ip("21DA:D3:0:2F3B:2AA:FF:FE28:9C5A") must beTrue   } } 相关讨论 有趣的是,它声称要检查它是否是一个有效地址,"验证所传递的ip是否是有效的IPv4或IPv6地址。",但实际上它仅检查它是否被格式化为有效地址。例如,1200:0000:AB00:1234:0000:2552:7777:1313是IPv6地址的有效格式,但是在测试方法返回时,它不是有效的IPv6地址。相信它认为241.54.113.65是有效的IPv4地址。

以下正则表达式仅适用于IPv6。组1与IP匹配。

1(([0-9a-fA-F]{0,4}:){1,7}[0-9a-fA-F]{0,4}) 相关讨论 +1不一定总有人类无法理解的完美的超级复杂正则表达式。我将使用它,因为我了解它的作用,并且就我而言,我可以确定如果我得到的东西类似于有效的ipv6,那么它就是有效的ipv6。 这不会匹配说:fe80 :: 1或2342:32fd :: 2d32

使用Ruby?尝试这个:

1/^(((?=.*(::))(?!.*\3.+\3))\3?|[\dA-F]{1,4}:)([\dA-F]{1,4}(\3|:\b)|\2){5}(([\dA-F]{1,4}(\3|:\b|$)|\2){2}|(((2[0-4]|1\d|[1-9])?\d|25[0-5])\.?\b){4})\z/i

查看其他答案中包含的模式,可以通过引用组和利用超前行为来改善许多好的模式。这是一个自引用模式的示例,如果需要,我将在PHP中使用该模式:

12345678910^(?(?[[:xdigit:]]{0,4}) # grab a sequence of up to 4 hex digits                                      # and name this pattern for usage later      (?                                      # as long as we can't match 3  (?&hgroup){1,6} # match our hex group 1 to 6 more times  (?:(?:     # match an ipv4 address or     (?2[0-5]|(?:2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3}(?&dgroup)     # match our hex group one last time     |(?&hex))$

注意:PHP为此有一个内置的过滤器,这将是一个更好的解决方案 图案。

Regex101分析

InetAddressUtils已定义了所有模式。我最终直接使用了他们的模式,并将其粘贴在这里以供参考:

12345678910111213141516171819private static final String IPV4_BASIC_PATTERN_STRING =        "(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.){3}" + // initial 3 fields, 0-255 followed by .         "([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])"; // final field, 0-255 private static final Pattern IPV4_PATTERN =     Pattern.compile("^" + IPV4_BASIC_PATTERN_STRING +"$"); private static final Pattern IPV4_MAPPED_IPV6_PATTERN = // TODO does not allow for redundant leading zeros         Pattern.compile("^::[fF]{4}:" + IPV4_BASIC_PATTERN_STRING +"$"); private static final Pattern IPV6_STD_PATTERN =     Pattern.compile(            "^[0-9a-fA-F]{1,4}(:[0-9a-fA-F]{1,4}){7}$"); private static final Pattern IPV6_HEX_COMPRESSED_PATTERN =     Pattern.compile(            "^(([0-9A-Fa-f]{1,4}(:[0-9A-Fa-f]{1,4}){0,5})?)" + // 0-6 hex fields             "::" +             "(([0-9A-Fa-f]{1,4}(:[0-9A-Fa-f]{1,4}){0,5})?)$"); // 0-6 hex fields

根据您的需求,近似如下所示:

1[0-9a-f:]+

可能就足够了(例如,与简单的日志文件grepping一样)。

很难找到适用于所有IPv6情况的正则表达式。它们通常很难维护,不容易阅读,并且可能导致性能问题。因此,我想分享一个我开发的替代解决方案:用于IPv6的正则表达式(RegEx)与IPv4分开

现在您可能会问:"此方法只能找到IPv6,如何在文本或文件中找到IPv6?"这里也有解决此问题的方法。

注意:如果您不想在.NET中使用IPAddress类,也可以将其替换为我的方法。它还涵盖了映射的IPv4和特殊情况,而IPAddress没有涵盖。

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123class IPv6 {     public List FindIPv6InFile(string filePath)     {         Char ch;         StringBuilder sbIPv6 = new StringBuilder();         List listIPv6 = new List();         StreamReader reader = new StreamReader(filePath);         do         {             bool hasColon = false;             int length = 0;             do             {                 ch = (char)reader.Read();                 if (IsEscapeChar(ch))                     break;                 //Check the first 5 chars, if it has colon, then continue appending to stringbuilder                 if (!hasColon && length < 5)                 {                     if (ch == ':')                     {                         hasColon = true;                     }                     sbIPv6.Append(ch.ToString());                 }                 else if (hasColon) //if no colon in first 5 chars, then dont append to stringbuilder                 {                     sbIPv6.Append(ch.ToString());                 }                 length++;             } while (!reader.EndOfStream);             if (hasColon && !listIPv6.Contains(sbIPv6.ToString()) && IsIPv6(sbIPv6.ToString()))             {                 listIPv6.Add(sbIPv6.ToString());             }             sbIPv6.Clear();         } while (!reader.EndOfStream);         reader.Close();         reader.Dispose();         return listIPv6;     }     public List FindIPv6InText(string text)     {         StringBuilder sbIPv6 = new StringBuilder();         List listIPv6 = new List();         for (int i = 0; i < text.Length; i++)         {             bool hasColon = false;             int length = 0;             do             {                 if (IsEscapeChar(text[length + i]))                     break;                 //Check the first 5 chars, if it has colon, then continue appending to stringbuilder                 if (!hasColon && length < 5)                 {                     if (text[length + i] == ':')                     {                         hasColon = true;                     }                     sbIPv6.Append(text[length + i].ToString());                 }                 else if (hasColon) //if no colon in first 5 chars, then dont append to stringbuilder                 {                     sbIPv6.Append(text[length + i].ToString());                 }                 length++;             } while (i + length != text.Length);             if (hasColon && !listIPv6.Contains(sbIPv6.ToString()) && IsIPv6(sbIPv6.ToString()))             {                 listIPv6.Add(sbIPv6.ToString());             }             i += length;             sbIPv6.Clear();         }         return listIPv6;     }     bool IsEscapeChar(char ch)     {         if (ch != ' ' && ch != ' ' && ch != ' ' && ch!='\t')         {             return false;         }         return true;     }     bool IsIPv6(string maybeIPv6)     {         IPAddress ip;         if (IPAddress.TryParse(maybeIPv6, out ip))         {             return ip.AddressFamily == AddressFamily.InterNetworkV6;         }         else         {             return false;         }     } }

在Java中,可以使用库类sun.net.util.IPAddressUtil:

1IPAddressUtil.isIPv6LiteralAddress(iPaddress); 相关讨论 sun.net。*是私有API。

这将适用于IPv4和IPv6:

1^(([0-9a-f]{0,4}:){1,7}[0-9a-f]{1,4}|([0-9]{1,3}\.){3}[0-9]{1,3})$ 相关讨论 它将无效地址与2个::实例匹配。例如2404:6800::4003:c02::8a 匹配无效的IPv4 666.666.666.666

您可以使用我为此目的制作的ipextract shell工具。它们基于regexp和grep。

用法:

1234$ ifconfig | ipextract6 fe80::1%lo0 ::1 fe80::7ed1:c3ff:feec:dee1%en0

这是我想出的,使用一些先行和命名组。这当然只是IPv6,但如果要添加IPv4,它不应干扰其他模式:

1(?=([0-9a-f]+(:[0-9a-f])*)?(?P::)(?!([0-9a-f]+:)*:))(::)?([0-9a-f]{1,4}:{1,2}){0,6}(?(wild)[0-9a-f]{0,4}|[0-9a-f]{1,4}:[0-9a-f]{1,4})

我使用python生成了以下代码,并与re模块一起使用。前瞻性断言可确保在地址中出现正确数量的点或冒号。它不支持IPv6表示法中的IPv4。

123pattern = '^(?=\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$)(?:(?:25[0-5]|[12][0-4][0-9]|1[5-9][0-9]|[1-9]?[0-9])\.?){4}$|(?=^(?:[0-9a-f]{0,4}:){2,7}[0-9a-f]{0,4}$)(?![^:]*::.+::[^:]*$)(?:(?=.*::.*)|(?=\w+:\w+:\w+:\w+:\w+:\w+:\w+:\w+))(?:(?:^|:)(?:[0-9a-f]{4}|[1-9a-f][0-9a-f]{0,3})){0,8}(?:::(?:[0-9a-f]{1,4}(?:$|:)){0,6})?$' result = re.match(pattern, ip) if result: result.group(0)

只需匹配来自原点的本地方括号(包括方括号)即可。我知道它不那么全面,但是在javascript中其他代码很难追踪主要是无法正常工作的问题,因此这似乎让我了解了我现在需要的东西。也不需要多余的字母A-F。

1^\[([0-9a-fA-F]{1,4})(\:{1,2})([0-9a-fA-F]{1,4})(\:{1,2})([0-9a-fA-F]{1,4})(\:{1,2})([0-9a-fA-F]{1,4})(\:{1,2})([0-9a-fA-F]{1,4})\]

Jinnko的版本已简化,我认为更好。

如上所述,获得IPv6文本表示形式的验证解析器的另一种方法是使用编程。这是一个完全符合RFC-4291和RFC-5952的文件。我已经用ANSI C编写了这段代码(与GCC一起使用,在Linux上通过了测试-与clang一起使用,在FreeBSD上通过了测试)。因此,它仅依赖于ANSI C标准库,因此可以在任何地方进行编译(我已经在FreeBSD的内核模块中将其用于IPv6解析)。

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889// IPv6 textual representation validating parser fully compliant with RFC-4291 and RFC-5952 // BSD-licensed / Copyright 2015-2017 Alexandre Fenyo #include #include #include #include #include typedef enum { false, true } bool; static const char hexdigits[] ="0123456789abcdef"; static int digit2int(const char digit) {   return strchr(hexdigits, digit) - hexdigits; } // This IPv6 address parser handles any valid textual representation according to RFC-4291 and RFC-5952. // Other representations will return -1. // // note that str input parameter has been modified when the function call returns // // parse_ipv6(char *str, struct in6_addr *retaddr) // parse textual representation of IPv6 addresses // str:     input arg // retaddr: output arg int parse_ipv6(char *str, struct in6_addr *retaddr) {   bool compressed_field_found = false;   unsigned char *_retaddr = (unsigned char *) retaddr;   char *_str = str;   char *delim;   bzero((void *) retaddr, sizeof(struct in6_addr));   if (!strlen(str) || strchr(str, ':') == NULL || (str[0] == ':' && str[1] != ':') ||       (strlen(str) >= 2 && str[strlen(str) - 1] == ':' && str[strlen(str) - 2] != ':')) return -1;   // convert transitional to standard textual representation   if (strchr(str, '.')) {     int ipv4bytes[4];     char *curp = strrchr(str, ':');     if (curp == NULL) return -1;     char *_curp = ++curp;     int i;     for (i = 0; i < 4; i++) {       char *nextsep = strchr(_curp, '.');       if (_curp[0] == '0' || (i < 3 && nextsep == NULL) || (i == 3 && nextsep != NULL)) return -1;       if (nextsep != NULL) *nextsep = 0;       int j;       for (j = 0; j < strlen(_curp); j++) if (_curp[j] < '0' || _curp[j] > '9') return -1;       if (strlen(_curp) > 3) return -1;       const long val = strtol(_curp, NULL, 10);       if (val < 0 || val > 255) return -1;       ipv4bytes[i] = val;       _curp = nextsep + 1;     }     sprintf(curp,"%x%02x:%x%02x", ipv4bytes[0], ipv4bytes[1], ipv4bytes[2], ipv4bytes[3]);   }   // parse standard textual representation   do {     if ((delim = strchr(_str, ':')) == _str || (delim == NULL && !strlen(_str))) {       if (delim == str) _str++;       else if (delim == NULL) return 0;       else {         if (compressed_field_found == true) return -1;         if (delim == str + strlen(str) - 1 && _retaddr != (unsigned char *) (retaddr + 1)) return 0;         compressed_field_found = true;         _str++;         int cnt = 0;         char *__str;         for (__str = _str; *__str; ) if (*(__str++) == ':') cnt++;         unsigned char *__retaddr = - 2 * ++cnt + (unsigned char *) (retaddr + 1);         if (__retaddr 4) return -1;       int i;       for (i = 0; i < delim - _str; i++)         if (!isxdigit(_str[i])) return -1;         else hexnum[4 - (delim - _str) + i] = tolower(_str[i]);       _str = delim + 1;       *(_retaddr++) = (digit2int(hexnum[0])


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3