'IP Address regex with netmasks
the format goal: require a.b.c.d/x where >>
- a is 1-3 digit num btw 1-223
- b, c, and d are 1-3 digit num btw 0-255 and *required
- x is 1 or 2 digit num btw 8-32 and the (/x) group is optional
here's the full regex I have now:
^(((?:22[0-3]|2([0-1])?\d?|([1-9][0-9]?|1[0-9]{2}))\.)((?:25[0-5]|2[0-4]\d|[01]?(\d{0,2}))\.){2}((25[0-5]|2[0-4]\d|[01]?(\d{0,2}))(\/([89]|[12]\d|3[0-2]))?),?\s?){1,50}$
**The problem I'm running into is: if "1.1.1." is entered (aka no 'd' group), it's passing validation. I want it to fail without the 'd' group **
here is the monstrosity broken into groups and w/ added spaces for my own sanity/readability: // start string, full group
^(
// a group, 1-223 with "."
((?:22[0-3]|2([0-1])?\d?|([1-9][0-9]?|1[0-9]{2}))\.)
// b and c groups 0-255 with "."
((?:25[0-5]|2[0-4]\d|[01]?(\d{0,2}))\.){2}
// d group, ends with optional netmask instead of "." // i tried making this non-optional as a group to solve my problem.
((25[0-5]|2[0-4]\d|[01]?(\d{0,2}))
// netmask
(\/([89]|[12]\d|3[0-2]))?)
// allow comma separated, optional space between, up to 50 IPs
,?\s?){1,50}$
(I'm realizing now that this comma is optional so they could split with only a space. Maybe I can prevent that too).
Solution 1:[1]
It is easier to see what your regex does if you format the pattern and add in-pattern comments.
Here is your current regex demo:
^(
((?:22[0-3]|2([0-1])?\d?|([1-9][0-9]?|1[0-9]{2}))\.) # a group, 1-223 with "."
((?:25[0-5]|2[0-4]\d|[01]?(\d{0,2}))\.){2} # b and c groups 0-255 with "."
((25[0-5]|2[0-4]\d|[01]?(\d{0,2})) # d group, ends with optional netmask instead of "." // i tried making this non-optional as a group to solve my problem.
(\/([89]|[12]\d|3[0-2]))?) # netmask
,?\s?){1,50}$ # allow comma separated, optional space between, up to 50 IPs
However, this regex is not only imprecise, it also leads to catastrophic backtracking with some long non-matching strings.
Your netmask pattern is fine. It seems you had issues with creating a numeric range regex. You can always resort to online utilities that can generate these patterns for you, I wrote one and shared on SO here.
So, a pattern for 1-223 range is (?:[1-9]|[1-9][0-9]|1[0-9]{2}|2[01][0-9]|22[0-3])
(you can manually reduce it to (?:[1-9]\d?|1\d{2}|2[01]\d|22[0-3])
) and a pattern for 0-255 range is (?:[0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])
(reduced to (?:[1-9]?\d|1\d{2}|2[0-4]\d|25[0-5])
)
You can see that using these patterns fixes the issue and makes the pattern CA-resistent:
^(?:
(?:[1-9]\d?|1\d{2}|2[01]\d|22[0-3])\. # a group, 1-223 with "."
(?:(?:[1-9]?\d|1\d{2}|2[0-4]\d|25[0-5])\.){2} # b and c groups 0-255 with "."
(?:[1-9]?\d|1\d{2}|2[0-4]\d|25[0-5]) # d group, ends with optional netmask instead of "."
(?:\/(?:[89]|[12]\d|3[0-2]))? # netmask
,?\s? # allow comma separated, optional space between
){1,50}$ # up to 50 IPs
See this regex demo.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | Wiktor Stribiżew |