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
CodePudding user response:
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
...
CodePudding user response:
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)}`));