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

(Alternate Solution) Validate IPV4 and IPV6 with wildcard (*) characters using Regex

我想使用正则表达式验证带有通配符 (*) 的 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 中进行验证。 请帮助我。

根据问题评论中的建议,我给出了验证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 的 效果很好。 我稍微调整了他的代码以满足我的要求。

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>