请在标记为重复的之前阅读
我无法创建或找到适用于所有IPv6格式的IPv6(我的测试用例如下)。我知道每个人都指出的这个问题:匹配有效IPv6地址的正则表达式,但是,它们都将IPv6与IPv4结合在一起,并且/或不适用于我的所有测试用例。
要求:
Coldfusion中工作的模式和一个在PL/SQL中工作的模式。PL/SQL中使用它,所以它的模式必须保持在512个字符的下面。而且Oracle只支持RegExp语言的一小部分。因此,ColdFusion模式可能最终会与PL/SQL模式不同,这是很好的,只要它们都能工作。下面是我正在尝试的最新模式:
^(?>(?>([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中不起作用的项
::实际上是一种有效的格式,谢谢@Steffann)。我从:http://publib.boulder.ibm.com/infocenter/iseries/v5r3/index.jsp?topic=%2Frzai2%2Frzai2ipv6addrformat.htm获得了测试用例8-11,并被告知:测试9和11用于IPv6地址前缀,而不是IPv6地址,因此它们不应该匹配。
最终结果,我需要他们在这样的陈述中工作:
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发布于 2014-02-21 20:52:27
有了@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发布于 2015-02-03 00:14:59
据我所研究,没有一个RegEx适用于所有的IPv6格式。即使是这样,它也是如此的复杂和难以维护(不容易读)。此外,它也可能导致性能问题。因此,我决定为此编写一个方法(函数)。您也可以随心所欲地添加任何特殊情况。我用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“。
发布于 2014-02-07 16:09:36
::是一个有效的IPv6地址(全零地址),那么为什么不接受它呢?
如果您不想接受用IPv6符号编写的最后32位的IPv4地址(为什么不接受,它们是有效的地址表示),那么只需撤销处理它们的正则表达式的最后一部分(从::(ffff开始)。
无论如何,正则表达式确实包含了IPv4 4-表示法部分中的一些错误。IPv4表示法只是编写IPv6地址的最后32位的另一种方式,正则表达式并不能处理所有有效的变体。此外,它甚至忘记转义.,所以它也会接受许多无效的字符串。
https://stackoverflow.com/questions/21631669
复制相似问题