views:

3160

answers:

8

I am after a regular expression that validates a percentage from 0 100 and allows two decimal places.

Does anyone know how to do this or know of good web site that has example of common regular expressions used for client side validation in javascript?

@Tom - Thanks for the questions. Ideally there would be no leading 0's or other trailing characters.

Thanks to all those who have replied so far. I have found the comments really interesting.

A: 

i could suggest this for a start regex tutorial

lock
A: 

(100|[0-9]{1,2})(\.[0-9]{1,2})?

That should be the regex you want. I suggest you to read Mastering Regular Expression and download RegexBuddy or The Regex Coach.

Julien Grenier
100.10 will be matched and should not be
Czimi
A: 

Given that your value is in str

str.match(/^(100(\.0{1,2})?|([0-9]?[0-9](\.[0-9]{1,2})))$/)
Czimi
this matches 05.50% which is kind of odd. leading and trailing 0's shouldn't be allowed.
Bill James
Hmm, well, maybe just leading 0's should be disallowed. 5.50% isn't meaningless compared to 5.5%
Bill James
Unfortunately this regex doesn't match 5 or 15 i. e. numbers without decimal places.
Alexander Prokofyev
+8  A: 

Rather than using regular expressions for this, I would simply convert the user's entered number to a floating point value, and then check for the range you want (0 to 100). Trying to do numeric range validation with regular expressions is almost always the wrong tool for the job.

var x = parseFloat(str);
if (isNaN(x) || x < 0 || x > 100) {
    // value is out of range
}
Greg Hewgill
I can't vote this up enough.
eyelidlessness
It seems, writing correct regex is often like solving a puzzle - unnecessary but challenging.
Alexander Prokofyev
Good, it doesn't check whenever x have more than 2 decimal, is was trivial to check it, something like this:var decSeparator=".";if((""+x).indexOf(decSeparator)<str.length-3){ alert("alert:Too much decimal!");}btw, if str is in this format: "12.12aaaa" still validate, but x is just correct.
kentaromiura
mmm, sorry in the code posted above i forgot a piece XD, the correct example is:var decimalSeparator=".",val=""+x; if(val.indexOf(decimalSeparator)<val.length-3){alert("too much decimal");}
kentaromiura
A: 

I propose this one:

(^100(\.0{1,2})?$)|(^([1-9]([0-9])?|0)(\.[0-9]{1,2})?$)

It matches 100, 100.0 and 100.00 using this part

^100(\.0{1,2})?$

and numbers like 0, 15, 99, 3.1, 21.67 using

^([1-9]([0-9])?|0)(\.[0-9]{1,2})?$

Note what leading zeros are prohibited, but trailing zeros are allowed (though no more than two decimal places).

Alexander Prokofyev
A: 
^100(\.(0){0,2})?$|^([1-9]?[0-9])(\.(\d{0,2}))?\%$

This would match:
100.00
optional "1-9" followed by a digit (this makes the int part), optionally followed by a dot and two digits


I can't comment because I don't have enough reputation, but from what I see, Greg Hewgill's example doesn't really work that well because parseFloat('15x') would simply return 15 which would match the 0<x<100 condition. Using parseFloat is clearly wrong because it doesn't validate the percentage value, it tries to force a validation. Some people around here are complaining about leading zeroes and some are ignoring trailing invalid characters. Maybe the author of the question should edit it and make clear what he needs.

Tom
Will match strings like "1.", "95.", "100." Probably regex should be corrected.
Alexander Prokofyev
+2  A: 

This reminds me of an old blog Entry By Alex Papadimoulis (of The Daily WTF fame) where he tells the following story:

"A client has asked me to build and install a custom shelving system. I'm at the point where I need to nail it, but I'm not sure what to use to pound the nails in. Should I use an old shoe or a glass bottle?"

How would you answer the question?

  1. It depends. If you are looking to pound a small (20lb) nail in something like drywall, you'll find it much easier to use the bottle, especially if the shoe is dirty. However, if you are trying to drive a heavy nail into some wood, go with the shoe: the bottle with shatter in your hand.

  2. There is something fundamentally wrong with the way you are building; you need to use real tools. Yes, it may involve a trip to the toolbox (or even to the hardware store), but doing it the right way is going to save a lot of time, money, and aggravation through the lifecycle of your product. You need to stop building things for money until you understand the basics of construction.

This is such a question where most people sees it as a challenge to come up with the correct regular expression to solve the problem, but it would be much better to just say that using regular expressions are using the wrong tool for the job.

The problem when trying to use regex to validate numeric ranges is that it is hard to change if the requirements for the allowed range is changes. Today the requirement may be to validate numbers between 0 and 100 and it is possible to write a regex for that which doesn't make your eyes bleed. But next week the requirment maybe changes so values between 0 and 315 are allowed. Good luck altering your regex.

The solution given by Greg Hewgill is probably better - even though it would validate "99fxx" as "99". But given the circumstances that might actually be ok.

mlarsen
A: 

@mlarsen: Is not that a regex here won't do the job better.

Remember that validation msut be done both on client and on server side, so something like:

100|(([1-9][0-9])|[0-9])(\.(([0-9][1-9])|[1-9]))?

would be a cross-language check, just beware of checking the input length with the output match length.

kentaromiura
And now you have a regex which matches this requirement. A week later the requirements changes so now your regex should match values between 0 and 255 instead. Good luck changing your regex and have it readable afterwards.
mlarsen
Yes, It's true, good point here, but in either case there are downside, so is just a matter of what you want to do...You see, I use to put regex in the configuration file, so if a requirement change, I already know where to modify the validation code.
kentaromiura