Stuart
Stuart

Reputation: 1574

Regular Expression for numbers allowing only 1 comma and decimal

I have this expression for valid number only...

^[0-9,-\.]+$

This works fine, but I need to ensure that a maximum of 1 , and 1 . can be entered? This needs to cater for different cultures so it doesn't matter to me which order the , and . come in.

Can anyone help with this?

Upvotes: 1

Views: 2787

Answers (3)

Martin Ender
Martin Ender

Reputation: 44289

If your regex flavor supports lookaheads you can use:

^(?=[^,],[^,]$)(?=[^.]\.[^.]$)[\d,.-]+$

If not, then you could do something like this:

^(?:[\d-]*,?[\d-]*\.?[\d-]*|[\d-]*\.[\d-]*,[\d-]*)$

But I find this is rather ugly.

Note that I changed your character class. [0-9] can be shortened to \d (note that dependent on your regex flavor this might match other Unicode digits than just 0-9), . does not need to be escaped inside character classes, and - belong at the beginning or the end of character class, otherwise they need to be escaped. Funnily enough, in your case it does not even make a difference, because ,-. creates a range of characters from , to . (in ASCII order). However all the characters in this range are incidentally ,, - and .. Lucky you ;)

However, both answers really just do what you are explicitly asking for. Your pattern will still match --.--34,---1--2 and stuff like that. If you really want to match a valid number with culture-independent decimal point you should probably use this instead:

^-?\d*([.,]\d+)?$

Of if you want to match a valid number with . decimal point and at most one , thousand-separator (or vice-versa), this:

^-?\d{0,3}(?:(?:,\d{3})?(?:\.\d+)?|(?:\.\d{3})?(?:\,\d+)?)$

I don't think there is a shorter version, really. Do not worry about all the ?:. They just make the subpatterns non-capturing. Since you do not need that anyway, it is usually a significant performance increase.

Upvotes: 1

Anirudha
Anirudha

Reputation: 32827

You can simply use this regex..it's quite simple and straightforward..

^(\d*|\d*\,\d*|\d*\.\d*|\d*\.\d*\,\d*|\d*\,\d*\.\d*)$

Upvotes: 0

inhan
inhan

Reputation: 7470

This is what I would probably use.

/^-?\d{0,2}((\.?\d{3})*(,\d+)?|(,?\d{3})*(\.\d+)?)$/
/*

^                   beginning of string
-?                  0 or 1 minus sign
\d{0,2}             0-2 numbers
(
    (\.?\d{3})*     0 or more (3-digit numbers, alternatively preceded by a dot)
    (,\d+)?         0 or 1 (comma and at least 1 number)
|                   or
    (,?\d{3})*      0 or more (3-digit numbers, alternatively preceded by a comma)
    (\.\d+)?        0 or 1 (dot and at least 1 number)
)
$                   end of string

*/

EDIT: You can change this into

/^-?\d{0,2}((\.?\d{3})*(,\d{1,2})?|(,?\d{3})*(\.\d{1,2})?)$/
                            ^^^                    ^^^

if you want to limit the floating part to 2 digits.

Upvotes: 0

Related Questions