IPv6 的正则表达式 (RegEx) 与 IPv4 分开

2021-12-24 00:00:00 regex ipv6 oracle coldfusion plsql

标记为重复前请阅读

我无法创建或找到适用于所有 IPv6 格式的 RegEx(我的测试用例如下).我知道每个人都指向的这个问题:匹配有效 IPv6 地址的正则表达式 但是,它们都将 IPv6 与 IPv4 结合在一起和/或不适用于我的所有测试用例.

I have not been able to create or find a RegEx that works for all IPv6 formats (my test cases are below). I am aware of this question that everyone points to: Regular expression that matches valid IPv6 addresses However, They all combine IPv6 with IPv4 and/or do not work with all my test cases.

要求:

  1. 我不希望它也验证 IPv4 值,我已经有一个单独的 IPv4 验证功能.
  2. 我需要一个适用于 Coldfusion 的模式和一个适用于 PL/SQL 的模式.
  3. 因为我在 PL/SQL 中使用它,所以它的模式必须少于 512 个字符.而 Oracle 只支持 RegExp 语言的一小部分.所以 ColdFusion 模式最终可能会与 PL/SQL 模式不同,这很好,只要它们都能工作.
  4. 最终结果不是一个很长的 RegEx,它可以拆分.
  1. I do not want it to also validate IPv4 values, I already have a separate validation function for IPv4.
  2. I need a pattern that works in Coldfusion and a pattern that works in PL/SQL.
  3. Because I'm using it in PL/SQL the pattern for it must stay under 512 characters. And Oracle supports only a narrow part of RegExp language. So the ColdFusion pattern could end up being different than the PL/SQL pattern, that is fine, so long as they both work.
  4. End result doesn't have be one long RegEx, it can be split up.

这是我正在尝试的最新模式:

Here is the latest pattern I'm trying out:

^(?>(?>([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}))$

这对于 ColdFusion 来说很接近,但不是 100%.它在 PL/SQL 中根本不起作用.

This comes close for ColdFusion but not 100%. It doesn't work at all in PL/SQL.

测试结果http://regex101.com/r/wI8cI0 粗体 项目是模式在 ColdFusion 中不适用的项目:

Test Results http://regex101.com/r/wI8cI0 The bold items are the ones the pattern doesn't work for in ColdFusion:

  1. 匹配
  2. 匹配
  3. 匹配
  4. 匹配
  5. 匹配
  6. ma​​tch(但@Michael Hampton 说这不应该匹配,因为它不是有效的 IPv6 地址,但其他人告诉我它是有效的,所以我不确定这个测试用例.)
  7. 匹配(:: 实际上是一种有效的格式,感谢@Sander Steffann.)
  8. 匹配
  9. 不匹配
  10. 匹配
  11. 不匹配
  12. 不匹配
  13. 不匹配
  14. 匹配
  15. 匹配
  16. 不匹配
  17. 不匹配
  18. 不匹配
  19. 不匹配
  1. match
  2. match
  3. match
  4. match
  5. match
  6. match (but @Michael Hampton says this should not match because it's not a valid IPv6 address, but others have told me it is valid, so I'm not sure about this test case.)
  7. match (:: is actually a valid format, thanks @Sander Steffann.)
  8. match
  9. no match
  10. match
  11. no match
  12. no match
  13. no match
  14. match
  15. match
  16. no match
  17. no match
  18. no match
  19. no match

我从以下位置获得了测试用例 8-11:http://publib.boulder.ibm.com/infocenter/iseries/v5r3/index.jsp?topic=%2Frzai2%2Frzai2ipv6addrformat.htm并被告知:测试 9 和 11 是针对 IPv6 地址前缀,而不是 IPv6 地址,因此不应匹配.

I got test cases 8-11 from: http://publib.boulder.ibm.com/infocenter/iseries/v5r3/index.jsp?topic=%2Frzai2%2Frzai2ipv6addrformat.htm And was told: Test 9 and 11 are for IPv6 address prefix, not an IPv6 address, so those should not be match.

最终结果,我需要它们在这样的语句中工作:

End result, I need them to work in statements like this:

ColdFusion:

ColdFusion:

<cfset IndexOfOccurrence1=REFind("^(?>(?>([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}))$",value[i])>

PL/SQL:

if ( REGEXP_LIKE(v,'^(?>(?>([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}))$','i') ) then

推荐答案

@nhahtdh 在这个答案中得到了很多帮助 https://stackoverflow.com/a/21943960/3112803 我发现分解它是最好的解决方案.下面是如何在 PL/SQL 中执行此操作的示例,但在其他语言中也可以这样做.我将在 ColdFusion 中做同样的事情.对于 PL/SQL,模式需要保持在 512 个字符以下,因此分解它非常有效并且易于理解.它通过了我在原始问题中的所有测试用例.

With much help from @nhahtdh in this answer https://stackoverflow.com/a/21943960/3112803 I have found breaking it up to be the best solution. Below is an example of how to do it in PL/SQL, but it could be done this way in other languages. I'll do the same in ColdFusion. For PL/SQL the pattern needed to stay under 512 characters so breaking it up works great and it is simple to understand. It passed all my test cases in the original question.

if (
    /* IPv6 expanded */
    REGEXP_LIKE(v, 'A[[:xdigit:]]{1,4}(:[[:xdigit:]]{1,4}){7}z')
    /* IPv6 shorthand */
    OR (NOT REGEXP_LIKE(v, 'A(.*?[[:xdigit:]](:|z)){8}')
    AND REGEXP_LIKE(v, 'A([[:xdigit:]]{1,4}(:[[:xdigit:]]{1,4}){0,6})?::([[:xdigit:]]{1,4}(:[[:xdigit:]]{1,4}){0,6})?z'))
    /* IPv6 dotted-quad notation, expanded */
    OR REGEXP_LIKE(v, 'A[[:xdigit:]]{1,4}(:[[:xdigit:]]{1,4}){5}:(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])(.(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])){3}z')
    /* IPv6 dotted-quad notation, shorthand */
    OR (NOT REGEXP_LIKE(v, 'A(.*?[[:xdigit:]]:){6}')
    AND REGEXP_LIKE(v, 'A([[:xdigit:]]{1,4}(:[[:xdigit:]]{1,4}){0,4})?::([[:xdigit:]]{1,4}:){0,5}(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])(.(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])){3}z'))
) then

相关文章