I think I created a working regular expression for what I need. Just wondering if anyone can break it or see a shorter way to write it.
The regular expression should validate the following…
- Dollar sign optional
- Negative numbers signified with parenthesis, not a minus
- If negative, dollar sign should be outside the parenthesis
- Commas are optional
- Max number is 999999.99
- Min number is (999999.99)
- Decimals do not have to be supplied, but if so, no more than two
digits
So here are some examples of valid ones…
9
$9
$0.99
($999,999.99)
(999999)
($999999)
(999,999)
99,999.9
This is what I have come up with:
^\$?(((\d{1,6}(\.\d{1,2})?)|(\d{1,3},\d{3}(\.\d{1,2})?)|\(((\d{1,6}(\.\d{1,2})?)|(\d{1,3},\d{3}(\.\d{1,2})?))\)))$
CORRECTION, my spec was wrong, if the dollar sign is used it must be INSIDE the parenthesis.
You can express “between one and six digits; comma before the last three digits is optional” a bit more tersely as
\d{1,3}(,?\d{3})?. This also allows you to include only two copies of(\.\d{1,2})?: one for positive and one for negative, instead of one for positive-without-comma, one for positive-with-comma, etc.Also,
\d{1,2}can be shortened slightly to\d\d?, though I’m not sure if that’s an improvement.So, barring some notation like
(?(1))to test if a backreference is set, here’s the shortest version I see:One perhaps-undesirable aspect of your regex, and of this one, is that they will allow something like
$00,012.7, even though no one uses leading zeroes that way. You can address that by requiring the first digit to be nonzero, and then adding a special case to handle$0and(0.12)and so on:Edited to add: using a lookahead assertion like F.J suggests in his/her answer, the latter can be shortened to: