Multiple ip addresses in single string - javascript

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.

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.

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.

Related

How I run the replace function one time?

I want the replaceFunction to run only one time. For now works correctly only on first time, E-1 return Ε-1 (APPLE) but when user try to edit text field again system detect
Ε-1 and return Ε-1 (APPLE) (APPLE)..
td.onchange = function(e) {
this.value = this.value.replace(/(\E-(\d+))/g, replaceFunction);
function replaceFunction(match) {
// add additional rules here for more cases
if (match === "E-1") return "Ε-1 (APPLE)";
if (match === "E-2") return "Ε-2 (SUMSUNG)";
.
.
.
if(match === "E-99") return "Ε-99 (LG)";
return match;
}
}
How I stop this?
You can use something like this one more condition:
if (match === "E-1" && match !== "Ε-1 (APPLE)") return "Ε-1 (APPLE)";
this can be optimized, if you put the mapping into object:
var map = {
"E-1": "Ε-1 (APPLE)",
...
}
if (map[match] && !map[match] !== match) { return map[match]; }
and for this to work you will need regex that also match the word after in bracket:
var names = ['APPLE', 'SAMSUNG'];
var re = new RegExp('(E-(\\d+))(?! \\((?:' + names.join('|') + ')\\))', 'g');
Yet another solution is to use only array (this will only work if you E-NUM match index in array)
var names = ['APPLE', 'SAMSUNG'];
var re = new RegExp('(E-(\\d+))(?! \\((?:' + names.join('|') + ')\\))', 'g');
// regex explanation, same as yours but \\d is because it's a string
// we create negative look ahead so we check if next text
// after E-1 is not " (" and any of the names.
// we use (?: to group what's inside it's the same as with ()
// but the value will not be captured so there will be
// no param in function for this group
// so this regex will be the same as yours but will not match "E-1 (APPLE)"
// only "E-1"
this.value = this.value.replace(re, replaceFunction);
function replaceFunction(match, eg, num) {
// convert string to number E starts
var i = parseInt(num, 10) - 1;
if (i <= names.length) {
return match + ' (' + names[i] + ')';
}
}
the regex and function can be created outside of the change function, so it don't create new function on each change.
When replacing, also optionally lookahead for a space and parentheses that come after. This way, in the replacer function, you can check to see if what follows is already the value you want (eg, (APPLE)). If it is, then do nothing - otherwise, replace with the new string:
const replacementsE = [
, // nothing for E-0
'APPLE',
'SUMSUNG',
];
td.onchange = function(e) {
td.value = td.value.replace(/E-(\d+)(?= \(([^)]+)\)|)/g, replaceFunction);
function replaceFunction(match, digits, followingString) {
const replacement = replacementsE[digits];
if (!replacement || replacement === followingString) {
return match;
}
return `E-${digits} (${replacement})`;
}
}
<input id="td">
What /E-(\d+)(?= \(([^)]+)\)|)/ does is:
E- - Match E-
(\d+) - Capture digits in a group
(?= \(([^)]+)\)|) Lookahead for either:
\(([^)]+)\) A literal (, followed by non-) characters, followed by ). If this is matched, the non-) characters will be the second capture group
| - OR match the empty string (so that the lookahead works)
The digits will be the first capture group; the digits variable in the callback. The non-) characters will be the second capture group; the followingString variable in the callback.
If you also want to permit the final ) to be deleted, then make the final ) optional, and also make sure the character set does not match spaces (so that the space following APPLE, with no end ), doesn't get matched):
const replacementsE = [
, // nothing for E-0
'APPLE',
'SUMSUNG',
];
td.onchange = function(e) {
td.value = td.value.replace(/E-(\d+)(?= \(([^) ]+)\)?|)/g, replaceFunction);
function replaceFunction(match, digits, followingString) {
const replacement = replacementsE[digits];
if (!replacement || replacement === followingString) {
return match;
}
console.log(followingString)
return `E-${digits} (${replacement})`;
}
}
<input id="td">
If you want to permit any number of characters before the final ) to be deleted, then check if the replacement startsWith the following string:
const replacementsE = [
, // nothing for E-0
'APPLE',
'SUMSUNG',
];
td.onchange = function(e) {
td.value = td.value.replace(/E-(\d+)(?= \(([^) ]+)\)?|)/g, replaceFunction);
function replaceFunction(match, digits, followingString, possibleTrailingParentheses) {
const replacement = replacementsE[digits];
if (!replacement || replacement === followingString || replacement.startsWith(followingString)) {
return match;
}
return `E-${digits} (${replacement})`;
}
}
<input id="td">

Regular Expression - 4 digits, with optional 1 or 2 decimal places

Have a regular expression issue that I can't seem to quite get.
Requirements:
- Value between 0-9999
- Optionally can add either one or two decimals ( eg, 0.01 - 9999.99)
I've got a regex test and it looks to pass but when using it in my SAPUI5 app it doesn't seem to be working.
https://regex101.com/r/kB7oJ2/13
JS code:
var iQuantity = parseFloat(oArticle._Quantity);
var regexp = new RegExp('^([0-9]{1,4})(\.[0-9]{1,2})?$').test(iQuantity);
console.log(iQuantity);
console.log(regexp);
if (regexp === false) {
return this.setItemToError(oInput, oArticle,
this.getResourceBundle().getText("regExp"));
}
Something like this perhaps:
var re = /^(([0-9]{1,4})(\.[0-9]{1,2})?)$/;
var match = re.exec(subject);
if (match != null) {
result = match[1];
} else {
result = "";
}
/^\d{1,digits_before_decimal}$|(?=^.{1,char_count_with_decimal}$)^\d{0,digits_before_decimal}.\d{0,digits_after_decimal}$/;
In your example it is
/^\d{1,4}$|(?=^.{1,7}$)^\d{0,4}.\d{0,2}$/

Test if all given char's are in string - Javascript

I'm looking for smart, fast and simple way to check if the string contains all of the predefined char's.
For example:
var required = 'cfov'; //These are the char's to test for.
var obj = {valid: 'vvcdfghoco'}; //Valid prop can contains any string.
//what I have so far::
var valid = obj.valid, i = 0;
for(; i < 4; i++) {
if(valid.indexOf(required.chatAt(i)) === -1) {
break;
}
}
if(i !== 3) {
alert('Invalid');
}
Can we do it in RegExp? if yes, any help plz!
Thanks in Advance.
You can build a lookahead regex for your search string:
var re = new RegExp(required.split('').map(function(a) {
return "(?=.*" + a + ")"; }).join(''));
//=> /(?=.*c)(?=.*f)(?=.*o)(?=.*v)/
As you note that this regex is adding a lookahead for each character in search string to make sure that all the individual chars are present in the subject.
Now test it:
re.test('vvcdfghoco')
true
re.test('vvcdghoco')
false
re.test('cdfghoco')
false
re.test('cdfghovco')
true
You can do this way:
var required = 'cfov'; //These are the char's to test for.
var valid = 'vvcdfghoco'; //Valid prop can contains any string.
var regex = new RegExp("^[" + valid + "]*$");
/* this line means:
from start ^ till * the end $ only the valid characters present in the class [] */
if (required.match(regex)) {
document.write('Valid');
}
else {
document.write('Invalid');
}
Hope it helps.

how to check if a string matches a pattern with asterisk

I have a list of files:
var files = [
"user_parse_info",
"user_parse_age",
"site_render_info",
"site_parse_name"
]
Now I have string a pattern:
var pattern = "site_*_name";
This should match only the last file.
How can I check this? Maybe an RegExp?
Yes, regular expression would be a better choice for this.
var _ = require('nimble');
var files = [
"user_parse_info",
"user_parse_age",
"site_render_info",
"site_parse_name"
];
var re = /^site_.*_name$/;
var result = _.filter(files, function (val) {
return re.test(val);
});
Using a regular expression means that you would need to escape some characters like . and $, otherwise they can give false positives or keep the pattern from matching anything.
You can just split the string on the asterisk and check the parts against the string:
var parts = pattern.split('*');
if (
str.length >= parts[0].length + parts[1].length &&
str.substr(0, parts[0].length) == parts[0] &&
str.substr(str.length - parts[1].length) == parts[1])
{
// matches
}
Demo: http://jsfiddle.net/Guffa/u8XEE/

Javascript find if english alphabets only

Am trying to find some text only if it contains english letters and numbers using Javascript/jQuery.
Am wondering what is the most efficient way to do this? Since there could be thousands of words, it should be as fast as possible and I don't want to use regex.
var names[0] = 'test';
var names[1] = 'हिन';
var names[2] = 'لعربية';
for (i=0;i<names.length;i++) {
if (names[i] == ENGLISHMATCHCODEHERE) {
// do something here
}
}
Thank you for your time.
A regular expression for this might be:
var english = /^[A-Za-z0-9]*$/;
Now, I don't know whether you'll want to include spaces and stuff like that; the regular expression could be expanded. You'd use it like this:
if (english.test(names[i])) // ...
Also see this: Regular expression to match non-English characters?
edit my brain filtered out the "I don't want to use a regex" because it failed the "isSilly()" test. You could always check the character code of each letter in the word, but that's going to be slower (maybe much slower) than letting the regex matcher work. The built-in regular expression engine is really fast.
When you're worried about performance, always do some simple tests first before making assumptions about the technology (unless you've got intimate knowledge of the technology already).
If you're dead set against using regexes, you could do something like this:
// Whatever valid characters you want here
var ENGLISH = {};
"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789".split("").forEach(function(ch) {
ENGLISH[ch] = true;
});
function stringIsEnglish(str) {
var index;
for (index = str.length - 1; index >= 0; --index) {
if (!ENGLISH[str.substring(index, index + 1)]) {
return false;
}
}
return true;
}
Live Example:
// Whatever valid characters you want here
var ENGLISH = {};
"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789".split("").forEach(function(ch) {
ENGLISH[ch] = true;
});
function stringIsEnglish(str) {
var index;
for (index = str.length - 1; index >= 0; --index) {
if (!ENGLISH[str.substring(index, index + 1)]) {
return false;
}
}
return true;
}
console.log("valid", stringIsEnglish("valid"));
console.log("invalid", stringIsEnglish("invalid!"));
...but a regex (/^[a-z0-9]*$/i.test(str)) would almost certainly be faster. It is in this synthetic benchmark, but those are often unreliable.
Iterate each character in the string and check if the key code is not between 65 and 122, which are the Latin alphabet, lowercase and uppercase.
If wished to add punctuations characters, add their keyCode to the check.
function isLatinString(s) {
var i, charCode;
for (i = s.length; i--;) {
charCode = s.charCodeAt(i)
if (charCode < 65 || charCode > 122)
return charCode
}
return true
}
// tests
[
"abxSDSzfgr",
"aAzZ123dsfsdfעחלעלחי",
"abc!",
"$abc",
"123abc",
" abc"
]
.forEach(s => console.log( isLatinString(s), s ))
Another way, using an explicit whitelist string to allow specific charatcers:
function isLatinString(s){
var c, whietlist = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
for( c in s ) // get each character in the argument string
// if whitelist string doesn't include the character, break
if( !whietlist.includes(s[c].toUpperCase()) )
return false
return true
}
// tests
[
"abCD",
"aAאב",
"abc!",
"$abc",
"1abc",
" abc"
]
.forEach(s => console.log( isLatinString(s), s ))
Using regex is the fastest way to do this I'm afraid. This to my knowledge should be the fastest algorithm:
var names = 'test',
var names[1] = 'हिन';
var names[2] = 'لعربية';
//algorithm follows
var r = /^[a-zA-Z0-9]+$/,
i = names.length;
while (--i) {
if (r.test(names[i])) {
// do something here
}
}
You should consider words that may contain special characters. For example {it's}, isn't it english?

Categories

Resources