Method 1 - regex simplified
No need to overcomplicate the regex. Just ensure that the string conforms with the general format (the following regex) and then test that each octet is < 256 as the code snippet below shows.
^\d{1,3}\.\d{1,3}(?:\.(?:\d{1,3}|\*)){2}$
^ Assert position at the start of the line
\d{1,3} Match a digit 1 to 3 times
\. Match . literally
\d{1,3} Match a digit 1 to 3 times
(?:\.(?:\d{1,3}|\*)){2} Match the following twice
\. Match . literally
(?:\d{1,3}|\*) Match either a digit 1 to 3 times or * literally\
$ Assert position at the end of the line
var a = [
// valid
"10.10.*.1",
"10.10.0.1",
"10.10.255.1",
"10.10.10.*",
"10.10.10.0",
"10.10.10.255",
// invalid
"256.1.1.1",
"*.1.1.1",
"1.1.1",
"1.1.1.1.1"
]
var r = /^\d{1,3}\.\d{1,3}(?:\.(?:\d{1,3}|\*)){2}$/
a.forEach(function(ip) {
console.log(`${ip}: ${r.test(ip) && ip.split('.').every(function(x) { return Number(x) < 256 || x === '*' })}`)
})
Method 2 - no regex
Alternatively, without even using regex:
var a = [
// valid
"10.10.*.1",
"10.10.0.1",
"10.10.255.1",
"10.10.10.*",
"10.10.10.0",
"10.10.10.255",
// invalid
"256.1.1.1",
"*.1.1.1",
"1.1.1",
"1.1.1.1.1"
]
a.forEach(function(ip) {
var octets = ip.split('.'),
valid = false
if(octets.length === 4) {
if(Number(octets[0]) < 256
&& Number(octets[1]) < 256
&& (Number(octets[2]) < 256 || octets[2] === '*')
&& (Number(octets[3]) < 256 || octets[3] === '*')
)
valid = true
}
console.log(`${ip}: ${valid}`)
})
Method 3 - single regex
This is the most bloated method, but it seems that's what you're looking for.
^(?:25[0-5]|2[0-4]\d|[01]?\d{1,2})\.(?:25[0-5]|2[0-4]\d|[01]?\d{1,2})(?:\.(?:25[0-5]|2[0-4]\d|[01]?\d{1,2}|\*)){2}$
var a = [
// valid
"10.10.*.1",
"10.10.0.1",
"10.10.255.1",
"10.10.10.*",
"10.10.10.0",
"10.10.10.255",
// invalid
"256.1.1.1",
"*.1.1.1",
"1.1.1",
"1.1.1.1.1"
]
var r = /^(?:25[0-5]|2[0-4]\d|[01]?\d{1,2})\.(?:25[0-5]|2[0-4]\d|[01]?\d{1,2})(?:\.(?:25[0-5]|2[0-4]\d|[01]?\d{1,2}|\*)){2}$/
a.forEach(function(ip) {
console.log(`${ip}: ${r.test(ip)}`)
})
/^\d+\.\d+(\.(?:\*|\d+)){2}$/