2

I want users to be allowed to enter numbers, up to 3 digits before the decimal place, with an optional decimal place and a maximum of 2 digits after the optional decimal place.

I want it to match: 12, 123, 123.5, 123.55, 123. I do not want it to match: abc, 1234, 123.555

What I have so far it: ^\d{0,3}(.?)\d{0,2}$

At the moment it is still matching 1234. I think I need to use the look behind operator somehow but I'm not sure how.

Thanks

Ciaran O'Neill
  • 2,572
  • 6
  • 34
  • 40

4 Answers4

3

Try this:

^\d{0,3}(?:\.\d{0,2})?$

Or better, to avoid just a .:

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

Specifically, note:

  • Escaping the dot, or it matches any character (except new lines), including more digits.
  • Made the whole decimal part optional, including the dot. That is - the decimal dot is not optional - it must be including if we are to match any digit from the decimal part.
  • Even if you have escaped the dot, ^\d{0,3}(\.?)\d{0,2}$ isn't correct. With the dot optional, it can match 12378: \d{0,3} matches 123, (\.?) doesn't match anything, and \d{0,2} matches 78.

Working example: http://rubular.com/r/OOw6Ucgdgq

Kobi
  • 135,331
  • 41
  • 252
  • 292
  • Both work great, but I'll probably use the first one as it's a bit easier to read!. What is the ?: operator doing? – Ciaran O'Neill Mar 24 '11 at 05:56
  • @Ciaran - Thanks. `(?: )` is designed to do nothing - it is a [non-capturing group](http://stackoverflow.com/questions/3512471/non-capturing-group) - a logical group, but its match isn't added to the result of the regex. – Kobi Mar 24 '11 at 06:01
  • This matches `.` and the empty string as well –  Mar 24 '11 at 06:19
  • @sln - the first regex does, that's why I added a second one. I try to do one as similar to the OP's as possible, and one from scratch. Note that the OP's regex also accepts an empty input and a single dot - it may be intented. For example, when an input field is empty, you may don't want to display a validation error. – Kobi Mar 24 '11 at 06:22
  • @Kobi -Well, the first regex was what the OP wanted, too bad you couldn't make that one tennable without alternations. Unfortunate for him he is using it (the first one). –  Mar 24 '11 at 07:03
  • +1 Correction, this answer looks good. `(?=.*\d)` could be added to the first version to force a value. –  Mar 24 '11 at 08:01
  • Didn't realise the first one would allow just a period. Second one it is so, thanks – Ciaran O'Neill Mar 24 '11 at 22:40
1

Maybe this (untested)

^(?=.*\d)\d{0,3}\.?(?<=\.)\d{0,2}$

Edit - the above is wrong.

@Kobi's answer is correct.

A lookahead could be added to his first version to insure a NOT just a dot or empty string.

^(?=.*\d)\d{0,3}(?:\.\d{0,2})?$

  • Not really. `\.?(?<=\.)` reads "optional dot, and then check you're after a dot", which is logically the same as just `\.`. A condition may work here, but I suspect it's too much, and isn't universally supported. Even without `(?<=\.)`, `(?=.*\d)` protects against `.`, but it can still match `12345`. – Kobi Mar 24 '11 at 05:54
  • Oh, I missed the optional dot. Nice catch! –  Mar 24 '11 at 06:04
  • @Kobi, "protects against `.` but can still match `12345`" ? How did you arive at that conclusion? `(?=.*\d)` guarantee's at least a digit. `\.?` is optional, `(?<=\.)` actually protects trailing digits, the `(?: )` group binds the optional `.digits`. You should read it a little closer. –  Mar 24 '11 at 06:35
  • @sln - That comment refers to an old version of your answer. I said "Even without `(?<=\.)`" `^(?=.*\d)\d{0,3}\.?\d{0,2}$` can match `12345`. To be honest, I'm not sure you fully understand what `\.?(?<=\.)` does. It is *exactly the same* as `\.`. – Kobi Mar 24 '11 at 06:45
  • @Kobi -Maybe you didn't see the "untested" in my old version. Thanks for the schooling? How's the new version from 40 minutes ago, got any questions? –  Mar 24 '11 at 06:59
  • @Kobi - none taken, you were correct though, `\.? (?<=\.)` does mean `\.` –  Mar 24 '11 at 07:45
1

What about this?

/^\d{0,2}(?:\d\.|\.\d|\d\.\d)?\d?$/
sawa
  • 165,429
  • 45
  • 277
  • 381
0

You have to put the combination of decimal point and the decimal numbers optional. In your regex, only the decimal number is optional. 1234 is accepted because 123 satisfy ^\d{0,3}, not existing decimal point satisfy (.?), and 4 satisfy \d{0,2}.

Kobi's answer provided you the corrected regex.

gouki
  • 4,382
  • 3
  • 20
  • 20