(替代解决方案)使用正则表达式使用通配符 (*) 验证 IPV4 和 IPV6

Posted

技术标签:

【中文标题】(替代解决方案)使用正则表达式使用通配符 (*) 验证 IPV4 和 IPV6【英文标题】:(Alternate Solution) Validate IPV4 and IPV6 with wildcard (*) characters using Regex 【发布时间】:2022-01-17 18:04:05 【问题描述】:

我想使用正则表达式验证带有通配符 (*) 的 IP 地址。 我为 IPV4 和 IPV6 提出了以下正则表达式,但这些并不能验证所有用例。

IPV4

^((([0-9]1,2)|(1[0-9]2,2)|(2[0-4][0-9])|(25[ 0-5])|*).)3(([0-9]1,2)|(1[0-9]2,2)|(2[0-4][0 -9])|(25[0-5])|*)$

此正则表达式与以下四种有效的 IPV4 格式 (https://regex101.com/r/RXf5yM/1) 不匹配。 我不确定我必须进行哪些更改才能允许这些。

192.*
192.0.*
192.*.2
*

IPV6

^\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]\d|1\d\d|[1-9]?\d)(.(25[0 -5]|2[0-4]\d|1\d\d|[1-9]?\d))3)|:))|(((([0-9A-Fa-f ]1,4)|*):)5(((:(([0-9A-Fa-f]1,4)|*))1,2)|:(( 25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(.(25[0-5]|2[0-4]\d| 1\d\d|[1-9]?\d))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]\d|1\d\d|[1-9]?\d)(.(25[0- 5]|2[0-4]\d|1\d\d|[1-9]?\d))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]\d|1\d\d |[1-9]?\d)(.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d))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]\d|1\d\d|[1-9]?\d)(.(25[0-5]|2[0-4]\d|1\d\ d|[1-9]?\d))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]\d|1\d\d|[1-9]?\d)(.(25[0 -5 ]|2[0-4]\d|1\d\d|[1-9]?\d))3))|:))|(:(((:(([0-9A- Fa-f]1,4)|*))1,7)|((:(([0-9A-Fa-f]1,4)|*))0,5 :((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(.(25[0-5]|2[0-4] \d|1\d\d|[1-9]?\d))3))|:)))\s*$

此正则表达式与以下三种有效的 IPV6 格式不匹配。(https://regex101.com/r/ereIrE/1)

2001:DB8:0:0:0:*
2001:*:1
*

但它匹配一个无效的 IPV6 值与 "::*" -> 2404:66:4003::*:804

我需要修改正则表达式以仅允许有效值。我是正则表达式和 IP 地址概念的新手,无法弄清楚这一点。我需要在 JS 和 Java 中进行验证。 请帮帮我。

【问题讨论】:

你必须使用正则表达式吗?使用 split() 仅验证 .或:取决于 ip4/6 查看这里***.com/questions/11301670/… IPv6 模式清楚地表明您不应尝试使用单个正则表达式进行验证。 从网络工作原理的角度来看,这个 192.*.2 可能不应该被允许 这里有一个如何在没有 regEx 的情况下解决它的示例,因为这有点失控:jsfiddle.net/rjmy9zsw/3 【参考方案1】:

根据问题 cmets 中的建议,我给出了验证 IPV6 和 IPV4 的 IP 地址的解决方案。我已经通过拆分 IP 地址验证了这一点。 PS - 我使用了一些我遇到的格式的 IPV6 示例。如果我遗漏了任何用例,请告诉我。

IPV6

function evalIp6(ipAddress) 
    var ipAddrList = ipAddress.split(":")     
    var count =ipAddress.split("::").length-1;   
    if(ipAddrList.length>8 && !(ipAddress.split(":").length == 9 && ipAddrList[ipAddrList.length-1]=="" && count == 1 ))
            //IPV6 Cannot have more than 8 groups
            //Second if check to allow '::' in end after 7 groups. Eg : 2001:db8:122:344:c0:2:2100::
     
      return false;
     
    if(count>1)//IPV6 cannot have more that one "::"
    
        return false;
    
   
    if(ipAddress.indexOf("::*") != -1 || ipAddress.indexOf("*::") != -1)//IPV6 cannot have consecutive wildcard(*) with "::" since it can have multiple combinations.
    
      return false;
     
    var isWildCardPresent = false;
    for (let i = 0; i < ipAddrList.length; i++) 

        if(!isIPV6Group(ipAddrList[i]))
        
            return false;
        
        if(ipAddrList[i]  == "*")
        
            isWildCardPresent = true;
        
        
    
   if(!isWildCardPresent && count == 0 && ipAddrList.length!=8)//Without wildcard and :: , less. than 8 groups present. So it is invalid.
   
        return false;
   
   
   
    return true



function isIPV6Group(x)

    var ipv6GroupRegex = "^(([0-9A-Fa-f]1,4)|\\*|)$";
    //Allows Numbers 0 to FFFF or * or empty string (for group between ::)
  ipv6GroupRegex = new RegExp(ipv6GroupRegex);

  return ipv6GroupRegex.test(x);





var IPAddrTestList = [
"2404:6800:4003:c02::8a",
"2404:6800:4003:804::200e",
"2001:4998:c:a06::2:4008",
"fe80::21d8:f50:c295:c4be",
"2001:cdba::e:9652",
"2001:cdba:0:0:0:0:3257:9652",
"2001:cdba::3257:9652",
"2001:cdba::1222",
"21DA:D3:0:2F3B:2AA:FF:FE28:9C5A",
"2001:cdba::1:2:3:3257:9652",
"1234:Fd2:2:1:89::4500",
"1234:Fd2:12:1:89::4500",
"1080:0:0:0:8:800:200C:417A",
"1080::8:800:200C:417A",
"3210::",
"::",
"2001:B07:6473:B409:C05C:AC2B:C9B9:CC42",
"2A0C:9A40:8170::1",
"64:FF9B::CD8B:6384",
"FE80::4ABA:4EFF:FED4:6455",
"FE80::3E5C:C4FF:FE3B:AC19",
"FE80::3E5C:C4FF:FEA6:D45D",
"FE80::266:86FF:FE05:7933",
"2A03:2880:F127:83:FACE:B00C:0:25DE",
"2A00:5A60::AD1:FF",
"a:b::",
"2001:470:b0b4:1:280:c6ff:fef2:9410",
"2001:868:100::3",
"2001:888:144a::a441:888:1002",
"::1",
"2001:db8:122:3c0:0:221::",
"2001:db8:122:c000:2:2100::",
"2001:db8:1c0:2:21::",
"2001:db8:c000:221::",
"2001:db8:122:344:c0:2:2100::",


//IPV6 With wildcard
"2001:DB8:0:0:0:*:*:*",
"2001:DB8::0:*",
"2001:DB8:0:0:0:*:0:1",
"2001:DB8:0:0:0:*",
"2001:*:1",
"*",

//After this everything invalid
"2404:66:4003::*:804",
"2404:66:4003:34:*:804:35:35:35",


//Invalid IPV6 without wildcard
"2404::4003:804::200e",
"2001:cdba:e:9652",
"2404:6800:40003:c02::8a",
"1:2:3:4:5:6:7:8:9",
"a::b::c",
"x:x:x:x:x:x:x:x",
"::2222:3333:4444:5555:7777:8888::",

//IPV4 mapped with IPV6
"::FFFF:1.2.3.4",
"2001:db8:122:344::192.0.2.33",
"64:ff9b::192.0.2.33",
"::FFFF:189.203.69.53",
"::FFFF:94.8.43.194",
"::FFFF:174.238.136.77",
"::FFFF:142.234.162.5"
]
var result = "";
for(var index=0;index<IPAddrTestList.length;index++)

  var resultObj = IPAddrTestList[index] + "---->" + evalIp6(IPAddrTestList[index]);  
  result = result+resultObj+'<br>';
 

document.getElementById("demo").innerhtml = result;
<!DOCTYPE html>
<html>
<body>
<p id="demo"></p>
</body>
</html>

IPV4

@Maximillian Dolbaum 的code 效果很好。 我稍微调整了他的代码以满足我的要求。

function evalIpv4(str) 
    var arr = str.split(".")
   
   var isWildCardPresent = false;
    for (var i = 0; i < arr.length; i++) 
            if(arr[i] === '*')
        
             isWildCardPresent = true;
        
        if (!(arr[i] === '*' || inRange(parseInt(arr[i]), 0, 255))) 
            return false
        
    
    if((arr.length < 4 && !isWildCardPresent)|| (arr.length > 4))//Less than 4 digits present without wildcard or more than 4 octets not allowed
    
        return false;
    
    return true


function inRange(x, min, max) 
    return x >= min && x <= max;




var IPAddrTestList = [
"192.192.192.192",
"*.*.1.1",
"*.1.1.*",
"*.*.1.*",
"192.*.23.34",
"*.192.23.*",
"192.0.*.0",
"192.*.*.*",
"192.*",//equal to 192.*.*.*
"192.0.*",//equal to 192.0.*.*
"*",//equal to *.*.*.*
"19.*.23",//equal to 19.*.23.*
"*.24.23",//equal to *.24.23.*,
"192.12",//false - less than 4 octets
"256.23.23.34"//false - 1st octet > 255
]

var result = "";
for(var index=0;index<IPAddrTestList.length;index++)

  var resultObj = IPAddrTestList[index] + "---->" + evalIpv4(IPAddrTestList[index]);  
  result = result+resultObj+'<br>';
 

document.getElementById("demo").innerHTML = result;
<!DOCTYPE html>
<html>
<body>
<p id="demo"></p>
</body>
</html>

【讨论】:

以上是关于(替代解决方案)使用正则表达式使用通配符 (*) 验证 IPV4 和 IPV6的主要内容,如果未能解决你的问题,请参考以下文章

rename命令中正则表达式的使用

Day15 - linux的特殊符号与正则表达式

使用正则表达式替代 HTML 解析

Shell学习之结合正则表达式与通配符的使用

正则表达式:擦洗 HTML

正则表达式的可变长度lookbehind-assertion替代方案