0

I'm trying to match the following, and i'm having a difficult time doing so.

I want to allow 0 to 100, or 0% to 100%. In my textfield, i strip the % out, so if they put in 100, it won't fail at the regex and skip the strip.

Therefore, i'd need a regex to allow 0 to 100 or 0% to 100%. 101 or 101% is invalid.

Presently, i have the following

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

But that allows 101 but not 101%

Please help! Any help would be greatly appreciated.

AlfRGB
  • 11
  • 1
  • 1
  • 1
    **Some people, when confronted with a problem, think “I know, I'll use regular expressions.” Now they have two problems..** - [Jamie Zawinski](http://www.jwz.org/) 1997 –  Feb 24 '11 at 22:23

8 Answers8

14

You're trying to use regex to do something that regex isn't meant to do. You have the javascript and python tags; you should use regex to ensure that the input is a number, and then use javascript or python to determine whether the number is too big or too small. It will be much easier that way.

eykanal
  • 26,437
  • 19
  • 82
  • 113
  • Also see http://stackoverflow.com/questions/4098086/to-use-or-not-to-use-regular-expressions/4098123#4098123. –  Feb 24 '11 at 21:20
  • Yeah don't use regex as one tool for everything, even if you can it'll almost certainly be completely unreadable even if it's fairly simple and may contain some strange corner cases. – Voo Feb 24 '11 at 22:16
9

Some people, when confronted with a problem, think “I know, I'll use regular expressions.” Now they have two problems.. - Jamie Zawinski 1997

In all seriousness, you are trying to do something that Regular Expressions aren't intended to do, which is perform logic. What you are asking is, does this string of characters contain a number, which is fine and if it does, is it >= 0 && <= 100 which isn't something a regular expression can or should be doing.

While the expression ^(\d{1,2}|100)%?$ will work to tell you if the input matches the pattern, and let you pull the number out using the group. The fact that the result falls into the >=0 && <= 100 range is a side effect. This apparent range checking behavior won't work for any other arbitrary range of numbers. Side effects should be avoided for maintainable code.

Is it the optimal solution? Is the intention obvious from just looking at the expression? I would argue no, not without some comments describing the intent.

JavaScript

I think a better more maintainable solution would be to use the parseInt() function and then explicitly compare the result to >= 0 and <= 100. Explicit is Better than Implicit and is more self documenting.

Python

You will still have to resort to a regular expression to validate the format and extract only the numbers and convert that using int(), testing against the valid range would be redundant but also more explicit. Using the regular expression might not be such a bad option in this case, as long as you comment the intention of the use of the regular expression.

Easier to escape: n-layered nested quotes or an iron maiden?

Community
  • 1
  • 1
4

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

  • either '100' or any number consisting of one or two digits
  • possibly followed by a percent sign.

Test it here: http://jsbin.com/azeya3.

Oh yes, and the first capture contains the number.

Martijn
  • 13,225
  • 3
  • 48
  • 58
1

use on javascript "parseInt"

parseInt does following:

"100" -> 100
"10k" -> 10
"100%" -> 100

after this, check if your number is smaller than 101.

example...

function parsePerc(value) {
   return parseInt(value) < 101;
}
Luke
  • 8,235
  • 3
  • 22
  • 36
1

The question is tagged "python", so I'll answer in Python:

def is0to100(num):
    try:
        return 0 <= int(num.rstrip('%')) <= 100
    except ValueError:
        return False

This returns True if the passed-in value, minus the possible trailing '%', is a valid integer between 0 and 100. I didn't benchmark it, but I'd put money that it's way faster than a regexp.

Kirk Strauser
  • 30,189
  • 5
  • 49
  • 65
0

Match 0 to 100

^100$|^[123456789][0-9]$|^[0-9]$

Match 0% to 100%

^100[%]$|^[123456789][0-9][%]$|^[0-9][%]$
Jason Williams
  • 2,740
  • 28
  • 36
0

In the spirit of @eykanal's answer, here's a regex:

(\d{1,3})%? works for me in Python with this.

My test text was:

101
100
100%
101%
0%
0
50%

That will get you just the number, which you can then parse and decide whether or not it's in your acceptable range.

nmichaels
  • 49,466
  • 12
  • 107
  • 135
  • That just matches 0 or 100, doesn't it? – BoltClock Feb 24 '11 at 21:18
  • @Martijn: I think your first comment can be deleted (since it comments on something covered in the answer), and therefore your second comment can be deleted too (since you've probably slept since then :) and then I can delete this comment too. – tzot Mar 19 '11 at 20:25
0

First, I agreed with eykanal and Jarrod Roberson

But then, it's so simple with a regex that I doesn't agree more and that it's the better solution according to me:

'(\d\d?|100)(?!\d)\Z'  and use of match()

I think that presenting in first position \d\d? for detecting numbers < 100 , and in second position the number 100 alone, is of more natural logic.

Also \d\d? is shorter and more rapidly understood than \d{1,2}

EDIT

better :

'(\d\d?|100)\D?\Z'

But these RE are for detection. Since the aim is to verify, this one is enough:

'(\d\d?|100)\Z'
eyquem
  • 26,771
  • 7
  • 38
  • 46