oracle配置ipv6_关于oracle:IPv6的正则表达式(RegEx)与IPv4分开

标记为重复之前请先阅读

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

要求:

我不想让它也验证IPv4值,我已经有一个单独的IPv4验证功能。

我需要在Coldfusion中工作的模式和在PL/SQL中工作的模式。

因为我在PL/SQL中使用它,所以它的模式必须少于512个字符。而且Oracle仅支持RegExp语言的一小部分。因此Coldfusion模式最终可能会与PL/SQL模式不同,只要它们都可以工作。

最终结果没有长的RegEx,可以将其拆分。

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

^(?>(?>([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中根本不起作用。

测试结果http://regex101.com/r/wI8cI0粗体项是该模式在Coldfusion中不起作用的项:

比赛

比赛

比赛

比赛

比赛

匹配(但是@Michael Hampton说这不应该匹配,因为它不是有效的IPv6地址,但是其他人告诉我它是有效的,所以我不确定这个测试用例。)

匹配(::实际上是有效格式,感谢@Sander Steffann。)

比赛

没有匹配

比赛

没有匹配

没有匹配

没有匹配

比赛

比赛

没有匹配

没有匹配

没有匹配

没有匹配

我从以下网址获得了测试案例8-11:http://publib.boulder.ibm.com/infocenter/iseries/v5r3/index.jsp?topic=%2Frzai2%2Frzai2ipv6addrformat.htm

并被告知:测试9和11是针对IPv6地址前缀的,而不是IPv6地址,因此它们不应匹配。

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

ColdFusion:

(?>([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

您的商品6无效。 正则表达式是正确的。 您的测试用例不是IPv4映射的IPv6地址的有效示例。 修复测试用例。

好。 做了一些进一步的研究,我认为第6项不是您所说的有效格式,但是这些是有效格式,但是RegEx却说它们不是:(这两种格式允许IPv6应用程序直接与IPv4应用程序通信)0:0:0:0:0:ffff:192.1.56.10和(以下两种格式用于隧道传输。它允许IPv6节点在IPv4基础结构之间进行通信)0:0:0:0:0:0:192.1.56.10和::192.1.56.1096(来自:publib.boulder.ibm.com/infocenter/iseries/v5r3/)

您在最终评论中提供的最后两个曾经是有效的,但是今天已经不再使用。 您链接的文档已有十多年的历史了...

不要将正则表达式用于IPv6解析。 这是一场噩梦。

据我研究,尚没有适用于所有IPv6格式的RegEx。即使有,它也是如此复杂且难以维护(不易阅读)。此外,它也可能导致性能问题。因此,我决定为此编写一种方法(函数)。您也可以根据需要轻松添加任何特殊情况。我已经用C#编写了代码,但是我认为您可以将此算法转换为任何语言:

class IPv6Validator

{

string charValidator = @"[A-Fa-f0-9]";

string IPv4Validation = @"^((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]?)$";

PUBLIC bool IsIPv6(string maybeIPv6)

{

IF (maybeIPv6 =="::")

{

RETURN TRUE;

}

int numberOfEmptyDigitGroups = 0;

int expectedDigitGroupsLength = 8;

string[] arrMaybeIPv6 = maybeIPv6.Split(':');

IF (arrMaybeIPv6.LENGTH > 9 || arrMaybeIPv6.LENGTH < 3)

{

RETURN FALSE;

}

FOR (int i = 0; i < arrMaybeIPv6.LENGTH; i++)

{

//IF IPv6 starts OR ends WITH"::" (ex ::1)

IF ((i == 0 || i == arrMaybeIPv6.LENGTH - 2) && IsEmptyDigitGroup(arrMaybeIPv6[i]) && IsEmptyDigitGroup(arrMaybeIPv6[i+1]))

{

expectedDigitGroupsLength = 9;

numberOfEmptyDigitGroups++;

i++;

}

ELSE IF (arrMaybeIPv6[i].TRIM() == string.Empty) //IF IPv6 contains :: (ex 1:2::3)

{

numberOfEmptyDigitGroups++;

}

//Cannot have more than one"::"  (ex ::1:2::3)

IF (numberOfEmptyDigitGroups > 1)

{

RETURN FALSE;

}

//Mapped IPv4 control

IF (i == arrMaybeIPv6.LENGTH - 1 && IsIPv4(arrMaybeIPv6[i]) && arrMaybeIPv6.LENGTH < 8)

{

RETURN TRUE;

}

ELSE IF (i == arrMaybeIPv6.LENGTH - 1 && HasSpecialCharInIPv6(arrMaybeIPv6[i], IsEmptyDigitGroup(arrMaybeIPv6[i - 1]))) //IF LAST digit GROUP contains special CHAR (ex fe80::3%eth0)

{

RETURN TRUE;

}

ELSE //IF NOT IPV4, CHECK the digits

{

//Cannot have more than 4 digits (ex 12345:1::)

IF (arrMaybeIPv6[i].LENGTH > 4)

{

RETURN FALSE;

}

//CHECK IF it has unvalid CHAR

foreach (CHAR ch IN arrMaybeIPv6[i])

{

IF (!IsIPv6Char(ch.ToString()))

{

RETURN FALSE;

}

}

}

//Checks IF it has extra digit (ex 1:2:3:4:5:6:7:8f:)

IF (i >= expectedDigitGroupsLength)

{

RETURN FALSE;

}

//IF it has missing digit AT LAST OR END (ex 1:2:3:4:5:6:7:)

IF ((i == 0 || i == arrMaybeIPv6.LENGTH - 1) && IsEmptyDigitGroup(arrMaybeIPv6[i]) && expectedDigitGroupsLength != 9)

{

RETURN FALSE;

}

//IF it has missing digits (ex 1:2:3:4:5:6)

IF (i == arrMaybeIPv6.LENGTH - 1 && numberOfEmptyDigitGroups == 0 && arrMaybeIPv6.LENGTH < 8)

{

RETURN FALSE;

}

}

RETURN TRUE;

}

bool IsIPv4(string lastDigitGroup)

{

//IF lastDigitGroup has special CHAR, THEN get the FIRST GROUP FOR IPV4 validation (ex ::123.12.2.1/60)

string maybeIPv4 = lastDigitGroup.Split('/','%')[0];

Match match = Regex.Match(maybeIPv4, IPv4Validation);

RETURN match.Success;

}

bool IsIPv6Char(string strChar)

{

Match match = Regex.Match(strChar, charValidator);

RETURN match.Success;

}

bool IsSpecialChar(CHAR ch)

{

IF (ch == '%' || ch == '/')

{

RETURN TRUE;

}

RETURN FALSE;

}

bool HasSpecialCharInIPv6(string lastDigitGroup, bool isPreviousDigitGroupEmpty)

{

FOR (int i = 0; i < lastDigitGroup.LENGTH; i++)

{

//IF cannot find ANY special CHAR AT FIRST 5 chars THEN leave the FOR LOOP

IF (i == 5)

break;

//IF the FIRST digit IS special CHAR, CHECK the previous digits TO be sure it IS a valid IPv6 (ex FE80::/10)

IF (i == 0 && IsSpecialChar(lastDigitGroup[i]) && isPreviousDigitGroupEmpty)

RETURN TRUE;

IF (i != 0 && IsSpecialChar(lastDigitGroup[i]))

RETURN TRUE;

IF (!IsIPv6Char(lastDigitGroup[i].ToString()))

RETURN FALSE;

}

RETURN FALSE;

}

bool IsEmptyDigitGroup(string digitGroup)

{

IF (digitGroup.TRIM() == string.Empty)

RETURN TRUE;

RETURN FALSE;

}

}

我还添加了其他方法,例如如何在文本或文件中搜索IPv6。您可以检查:匹配有效IPv6地址的正则表达式

编辑摘要:映射的ipv4和特殊字符已被覆盖,例如" :: 123.23.23.23"," fe80 :: 3%eth0"," :: ffff:192.1.56.10/96"。

::是有效的IPv6地址(全零地址),那么为什么不接受它呢?

而且,如果您不想接受使用IPv4表示法写入的最后32位的IPv6地址(为什么不接受,它们是有效的地址表示形式),则只需撤销处理它们的regex的最后一部分(以)。

无论如何,正则表达式确实在IPv4注释部分中包含一些错误。 IPv4表示法是写入IPv6地址的后32位的另一种方式,而regex不能处理该地址的所有有效变体。此外,它甚至忘记转义.,因此它还将接受许多无效的字符串。

关于::,我没想到,很酷,我会接受的。关于另一个,我确实想接受ABCD:ABCD:ABCD:ABCD:ABCD:ABCD:192.168.158.190的说法,该说法无效。 regex101.com/r/mO4hJ2这是我用于IPv4 (((2[0-4]\d|25[0-5]|[01]?\d\d?)\.){3}(2[0-4]\d|25[0-5]|[01]?\d\d?))的RegExp。我不确定如何添加它来解决您提到的IPv4问题。

我不明白,那么您为什么要问"我需要一个RegEx用于IPv6,而不将其与IPv4结合使用"?

如果确实要接受IPv4地址表示法,则需要更改正则表达式的最后一部分,以使其接受以IPv4表示法结尾的双冒号(正则表达式的第一部分)的每个可能位置。我建议使用现有的地址解析例程,而不是尝试将所有内容放入一个复杂的(因此容易出错的)正则表达式中。

我的意思是"我需要一个RegEx来与IPv4结合使用而不将其与IPv4结合使用"是:在我链接到的另一篇文章中,它们都是验证单个IPv4值(例如255.255.255.0)或IPv6值(例如, ABCD:ABCD:ABCD:ABCD:ABCD:ABCD)。我只需要IPv6,但应允许使用IPv4映射的IPv6格式(45字节):ABCD:ABCD:ABCD:ABCD:ABCD:ABCD:192.168.158.190(stackoverflow.com/a/7477384/3112803)。我似乎可以开始使用后者。 regex101.com/r/dG0cN9谢谢,我会继续愚弄它。

在@nhahtdh的大量帮助下,我找到了将其分解为最佳解决方案的方法,该回答为https://stackoverflow.com/a/21943960/3112803。以下是在PL/SQL中如何执行此操作的示例,但是可以在其他语言中以这种方式执行。我将在ColdFusion中执行相同的操作。对于PL/SQL,该模式需要保持在512个字符以内,因此将其分解很有效,而且很容易理解。它通过了我在原始问题中的所有测试用例。

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

你可能感兴趣的:(oracle配置ipv6)