I have the following regex that allows any number (x), or comma separated numbers (x,x), or any range (x-x) for an input on my page:
^\d+(?:(?:\s*-\s*\d+)?|(?:\s*,\s*\d+)*)$
This works perfectly but I have a new requirement. I need to allow the user to label what they are defining and allow that if it's valid. For example, they can say: Buildings: 1000-1010 or Buildings: 1001,1002.
Buildings: must be in the beginning of the string followed a colon followed by the rest. If they don't specify I won't know what they are saying.
Currently Buildings is the only label they can define, but I know more will be coming so I would also like to be able to specify that, if possible. But hopefully I can figure it out if I figure out how to allow one:
let input = 'Buildings: 1000-1001';
/^\d+(?:(?:\s*-\s*\d+)?|(?:\s*,\s*\d+)*\s*,?)$/.test(input); // should be ok
input = 'Buildings: 1000';
/^\d+(?:(?:\s*-\s*\d+)?|(?:\s*,\s*\d+)*\s*,?)$/.test(input); // should be ok
input = 'Buildings: 1000,2002';
/^\d+(?:(?:\s*-\s*\d+)?|(?:\s*,\s*\d+)*\s*,?)$/.test(input); // should be ok
For future, say I have an array of labels:
const categories: ['Buildings', 'Cars', 'Houses'];
To loop over this list and run the test and include the variable's value in the regex. Is it possible?
Are you supposed to hardcode the text? I started trying that but I kept getting errors.
Thank you
A simpler regex should do the trick along with some format strings.
for example a simpler regex like /\d+?([,-]\d+?)*?$/ should do fine matching all three of your examples.
And for the string substitution using the new RegExp syntax will allow you to use standard format strings.
For Example:
const categories = ['Buildings', 'Cars', 'Houses'];
categories.forEach((i) => {
let input = 'Buildings: 1000-1001';
let re = new RegExp(`${i}: \\d+?([,-]\\d+?)*?$`);
console.log(re.test(input));
input = 'Buildings: 1000';
re = new RegExp(`${i}: \\d+?([,-]\\d+?)*?$`);
console.log(re.test(input));
input = 'Buildings: 1000,2002,2003,2034';
re = new RegExp(`${i}: \\d+?([,-]\\d+?)*?$`);
console.log(re.test(input));
input = 'Buildings: 1000,2002';
re = new RegExp(`${i}: \\d+?([,-]\\d+?)*?$`);
console.log(re.test(input));
});
OUTPUT : Only the first 4 print True because Only the first element of the array is in each of the inputs.
true
true
true
true
false
false
...
If the labels do not contain any special regex meta character, you might shorten the pattern and use an alternation
^(?:Buildings|Cars|Houses):\s*\d+(?:\s*[-,]\s*\d+)*$
See a regex demo.
const categories = ['Buildings', 'Cars', 'Houses'];
const regex = new RegExp(`^(?:${categories.join("|")}):\\s*\\d+(?:\\s*[-,]\\s*\\d+)*$`);
[
"Buildings: 1000-1001",
"Buildings: 1000",
"Buildings: 1000,2002",
"Test: 1000,2002"
].forEach(s => console.log(`${s} --> ${regex.test(s)}`));