In a regular expression, match one thing or another, or both

Yes, you can match all of these with such an expression:

/^[0-9]*\.?[0-9]+$/

Note, it also doesn't match the empty string (your last condition).


The fully general method, given regexes /^A$/ and /^B$/ is:

/^(A|B|AB)$/

i.e.

/^([0-9]+|\.[0-9]+|[0-9]+\.[0-9]+)$/

Note the others have used the structure of your example to make a simplification. Specifically, they (implicitly) factorised it, to pull out the common [0-9]* and [0-9]+ factors on the left and right.

The working for this is:

  • all the elements of the alternation end in [0-9]+, so pull that out: /^(|\.|[0-9]+\.)[0-9]+$/
  • Now we have the possibility of the empty string in the alternation, so rewrite it using ? (i.e. use the equivalence (|a|b) = (a|b)?): /^(\.|[0-9]+\.)?[0-9]+$/
  • Again, an alternation with a common suffix (\. this time): /^((|[0-9]+)\.)?[0-9]+$/
  • the pattern (|a+) is the same as a*, so, finally: /^([0-9]*\.)?[0-9]+$/

Nice answer by huon (and a bit of brain-twister to follow it along to the end). For anyone looking for a quick and simple answer to the title of this question, 'In a regular expression, match one thing or another, or both', it's worth mentioning that even (A|B|AB) can be simplified to:

A|A?B

Handy if B is a bit more complex.

Now, as c0d3rman's observed, this, in itself, will never match AB. It will only match A and B. (A|B|AB has the same issue.) What I left out was the all-important context of the original question, where the start and end of the string are also being matched. Here it is, written out fully:

^(A|A?B)$

Better still, just switch the order as c0d3rman recommended, and you can use it anywhere:

A?B|A