Reputation: 13
I have that kind of datas :
172.12.1.3;185.16.6.13;...
And sometimes the submask so it could be :
172.12.1.3;185.16.6.13/32;172.12.1.4;...
So I wanted to use regex (in js) to be sure each ip address is correct using ";" as separator.
It should not be too difficult, but even with a few research i've just manage to do something like this :
/^(((^|\.?)(1[0-9]{2}|[1-9][0-9]|[0-9]|2[0-4][0-9]|25[0-5])){4}(\;|$))*$/
Btw I know that I should, but I'm not really into regex...
Can someone give me a hand please ?
edit :
So i've tried something like this :
var poolIp = v.split(";");
var ipAddress = /^(((^|\.?)(1[0-9]{2}|[1-9][0-9]|[0-9]|2[0-4][0-9]|25[0-5])){4}(\;|$))*$/;
var ret = true;
for (var i = 0; i < poolIp.length; i++) {
var matches = ipAddress.exec(poolIp[i]);
if (!matches) {
ret = false;
}
}
return ret;
And it's way better, but ip address with submask is not valid and ip with 3 digits are valid.
Upvotes: 1
Views: 897
Reputation: 626754
You may use the following function to validate such strings of IP addresses. Note that the port number validation can be enhanced, I just check if the value is numeric.
function checkIsIPV4s(entry) {
var ips = entry.split(';'); // Split into separate IPs
for (var ip of ips) {
var blocks = ip.split(/[.\/]/); // Split with dot and slash
if(blocks.length === 5) { // If there are 5 blocks,
var last = blocks.pop(); // remove the last one
if (!/^\d+$/.test(last)) { // and check if it is numeric
return false; // if not - FALSE
}
}
if(blocks.length === 4) { // If block number is 4
var res = blocks.every(function(block) { // check each part
return parseInt(block,10) >=0 && parseInt(block,10) <= 255;
});
if (!res) {return false; } // If any part is not in 0..255 - FALSE
} else {
return false; // If block number is not 4 - FALSE
}
}
return true;
}
var str = "172.12.1.3;185.16.6.13/32;172.12.1.4;255.255.255.255";
console.log(checkIsIPV4s(str));
str2 = "172.12.1.34444;185.16.6.13/32";
console.log(checkIsIPV4s(str2));
However, there is a way to use a huge and unreadable regex, too. Adding this just to show that it is possible to do it with a regex:
/^(?:(?:\d{1,2}|1\d{2}|2(?:[0-4]\d|5[0-5]))\.){3}(?:\d{1,2}|1\d{2}|2(?:[0-4]\d|5[0-5]))(?:\/\d+)?(?:;(?:(?:\d{1,2}|1\d{2}|2(?:[0-4]\d|5[0-5]))\.){3}(?:\d{1,2}|1\d{2}|2(?:[0-4]\d|5[0-5]))(?:\/\d+)?)*$/
See the regex demo
The pattern matches:
^
- start of string(?:(?:\d{1,2}|1\d{2}|2(?:[0-4]\d|5[0-5]))\.){3}(?:\d{1,2}|1\d{2}|2(?:[0-4]\d|5[0-5]))(?:\/\d+)?
- a single IP pattern (all up to (?:\/\d+)?
) with an optional port number ((?:\/\d+)?
)(?:
- the non-capturing group start
;
- the separator(?:(?:\d{1,2}|1\d{2}|2(?:[0-4]\d|5[0-5]))\.){3}(?:\d{1,2}|1\d{2}|2(?:[0-4]\d|5[0-5]))(?:\/\d+)?
- the single IP pattern, same as above)*
- 0 or more occurrences of the non-capturing group sequences$
- end of string.Upvotes: 2
Reputation: 17617
This should do it:
var re = /^(;?[1-9][\d]{1,2}(\.[\d]{1,3}){3}(\/[\d]{1,3})?)+$/
re.test('172.12.1.3;185.16.6.13/32;172.12.1.4') // true
re.test('172.12.1.3;185.16.6.13/32;172.12.1') // false
re.test('072.12.1.3;185.16.6.13/32;172.12.1.4') // false
Or splitting them up:
var re = /^[1-9][\d]{1,2}(\.[\d]{1,3}){3}(\/[\d]{1,3})?$/
var ip1 = '172.12.1.3;185.16.6.13/32;172.12.1.4'.split(';');
var ip2 = '172.12.1.3;185.16.6.13/32;172.12.1'.split(';');
var ip3 = '072.12.1.3;185.16.6.13/32;172.12.1.4'.split(';');
ip1.every((ip) => re.test(ip));
ip2.every((ip) => re.test(ip));
ip3.every((ip) => re.test(ip));
You can use http://regexr.com/ to test your regexp, and read about Array.every here.
Upvotes: 1