Home > database >  How to allow only one comma and one "-" between numbers using regex and .test()?
How to allow only one comma and one "-" between numbers using regex and .test()?

Time:12-08

I have an issue with Regex. How I can check a string with numbers, special symbols like range symbol - and comma? I need to check string with that rules:

  • Only numbers, , and -. No letters, other symbols, etc.
  • Only one , between 2 numbers
  • Only one -, between 2 numbers
  • Don't allow - and , at the start and end of the string
  • Don't allow , after - or - after ,
"10,11-12,34" // correct
"1,2-3,4-5,6-11,12,13-14,16" // correct

",10,11-12,34" // incorrect
"-10,11-12,34" // incorrect    
"10,,11-12,34" // incorrect    
"10,11--12,34" // incorrect
"10,-11-12,34" // incorrect
"10,11-12,-,34" // incorrect    
"10,11-12,34," // incorrect
"10,11-12,34-" // incorrect

I'll be glad for any help. Thanks

CodePudding user response:

/^\d (?:-\d )?(?:,\d (?:-\d )?) $/ should do it. Breakdown:

  • ^ - start of input
  • \d - one or more digits
  • (?:-\d ) - non-capturing group allowing a - followed by one or more digits
  • ? - makes the group above optional
  • (?:,\d (?:-\d )?) - non-capturing group allowing a , followed by the same as above, to allow multiple numbers or ranges with commas separating them
  • - allow that group to repeat one or more times (see below)
  • $ - end of input

const tests = [
    { string: "10,11-12,34", good: true },
    { string: ",10,11-12,34", good: false },
    { string: "-10,11-12,34", good: false },
    { string: "10,,11-12,34", good: false },
    { string: "10,11--12,34", good: false },
    { string: "10,-11-12,34", good: false },
    { string: "10,11-12,-,34", good: false },
    { string: "10,11-12,34,", good: false },
    { string: "10,11-12,34-", good: false },
    { string: "1,2-3,4-5,6-11,12,13-14,16", good: true },
];

const rex = /^\d (?:-\d )?(?:,\d (?:-\d )?) $/;

for (const { string, good } of tests) {
    const result = rex.test(string);
    const message = result === good ? "OK" : "<== ERROR";
    console.log(`${JSON.stringify(string)} => ${result} ${message}`);
}
.as-console-wrapper {
    max-height: 100% !important;
}

If a single number like 15 or a single range like 15-20 is valid, change the near the end to * for "zero or more times" on the non-capturing group that allows the comma followed by more: /^\d (?:-\d )?(?:,\d (?:-\d )?)*$/

const tests = [
    { string: "10,11-12,34", good: true },
    { string: ",10,11-12,34", good: false },
    { string: "-10,11-12,34", good: false },
    { string: "10,,11-12,34", good: false },
    { string: "10,11--12,34", good: false },
    { string: "10,-11-12,34", good: false },
    { string: "10,11-12,-,34", good: false },
    { string: "10,11-12,34,", good: false },
    { string: "10,11-12,34-", good: false },
    { string: "1,2-3,4-5,6-11,12,13-14,16", good: true },
    { string: "15", good: true },
    { string: "15-20", good: true },
];

const rex = /^\d (?:-\d )?(?:,\d (?:-\d )?)*$/;

for (const { string, good } of tests) {
    const result = rex.test(string);
    const message = result === good ? "OK" : "<== ERROR";
    console.log(`${JSON.stringify(string)} => ${result} ${message}`);
}
.as-console-wrapper {
    max-height: 100% !important;
}

  • Related