Zanko Zanko - 4 months ago 12
Javascript Question

Regex for digits and hyphen only

I am trying to understand regex, for digits of length 10 I can simply do

/^[0-9]{10}$/


for hyphen only I can do

/^[-]$/


combining the two using group expression will result in

/^([0-9]{10})|([-])$/


This expression does not work as intended, it somehow will match part of the string instead of not match at all if the string is invalid.

enter image description here

How do I make the regex expression that accepts only "-" or 10 digits?

Answer

It would have worked fine to combine your two regexps exactly as you had them. In other words, just use the alternation/pipe operator to combine

/^[0-9]{10}$/

and

/^[-]$/

as is, directly into

/^[0-9]{10}$|^[-]$/
 ↑↑↑↑↑↑↑↑↑↑↑ ↑↑↑↑↑     YOUR ORIGINAL REGEXPS, COMBINED AS IS WITH |

This can be represented as

Regular expression visualization

and that would have worked fine. As others have pointed out, you don't need to specify the hyphen in a character class, so

/^[0-9]{10}$|^-$/
              ↑        SIMPLIFY [-] TO JUST -

Now, we notice that each of the two alternatives has a ^ at the beginning and a $ at the end. That is a bit duplicative, and it also makes it little harder to see immediately that the regexp is always matching things from beginning to end. Therefore, we can rewrite this, as explained in other answers, by taking the ^ and $ out of both sub-regexps, and combine their contents using the grouping operator ():

/^([0-9]{10}|-)$/
  ↑↑↑↑↑↑↑↑↑↑↑↑↑        GROUP REGEXP CONTENTS WITH PARENS, WITH ANCHORS OUTSIDE

The corresponding visualization is

Regular expression visualization

That would also work fine, but you could use \d instead of [0-9], so the final, simplest version is:

/^(\d{10}|-)$/
   ↑↑                  USE \d FOR DIGITS

and this visualizes as

Regular expression visualization

If for some reason you don't want to "capture" the group, use (?:, as in

/^(?:\d{10}|-)$/
   ↑↑                  DON'T CAPTURE THE GROUP

and the visualization now shows that group is not captured:

Regular expression visualization

By the way, in your original attempt to combine the two regexps, I noticed that you parenthesized them as in

/^([0-9]{10})|([-])$/
  ↑↑↑↑↑↑↑↑↑↑↑ ↑↑↑↑↑    YOU PARENTHESIZED THE SUB-REGEXPS

But actually this is not necessary, because the pipe (alternation, of "or") operator has low precedence already (actually it has the lowest precedence of any regexp operator); "low precedence" means it will apply only after things on both side are already processed, so what you wrote here is identical to

/^[0-9]{10}|[-]$/

which, however, still won't work for the reasons mentioned in other answers, as is clear from its visualization:

Regular expression visualization

Comments