IPv6 的正则表达式 (RegEx) 与 IPv4 分开
标记为重复前请阅读
我无法创建或找到适用于所有 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.
要求:
- 我不希望它也验证 IPv4 值,我已经有一个单独的 IPv4 验证功能.
- 我需要一个适用于
Coldfusion
的模式和一个适用于PL/SQL
的模式. - 因为我在
PL/SQL
中使用它,所以它的模式必须少于 512 个字符.而 Oracle 只支持 RegExp 语言的一小部分.所以ColdFusion
模式最终可能会与PL/SQL
模式不同,这很好,只要它们都能工作. - 最终结果不是一个很长的 RegEx,它可以拆分.
- I do not want it to also validate IPv4 values, I already have a separate validation function for IPv4.
- I need a pattern that works in
Coldfusion
and a pattern that works inPL/SQL
. - 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 theColdFusion
pattern could end up being different than thePL/SQL
pattern, that is fine, so long as they both work. - 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
:
- 匹配
- 匹配
- 匹配
- 匹配
- 匹配
- match(但@Michael Hampton 说这不应该匹配,因为它不是有效的 IPv6 地址,但其他人告诉我它是有效的,所以我不确定这个测试用例.)
- 匹配(
::
实际上是一种有效的格式,感谢@Sander Steffann.) - 匹配
- 不匹配
- 匹配
- 不匹配
- 不匹配
- 不匹配
- 匹配
- 匹配
- 不匹配
- 不匹配
- 不匹配
- 不匹配
- match
- match
- match
- match
- match
- 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.)
- match (
::
is actually a valid format, thanks @Sander Steffann.) - match
- no match
- match
- no match
- no match
- no match
- match
- match
- no match
- no match
- no match
- 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
相关文章