5

I'm trying to build up some regular expressions to validate some textbox controls. I have done some research and testing but cannot get this one working. Examples of what i am trying to create regular expressions for are as follows:

  1. Range 0-45, 0 decimal places
  2. Range 0-20, 2 decimal places
  3. Range 16-65, 0 decimal places
  4. Range 0-99, 2 decimal places
  5. Range 0-1500000, 0 decimal places
  6. Range 0-200, 1 decimal place

For 1 and 5 respectively, I have used

([0-9]|[0-9]\d|45)$  
([0-9]|[0-9]\d|1500000)$  

The first one I am having problems for is an age range of 16-65 (inclusive), where I want no decimal places. After a post on here (Regular expression to allow numbers between -90.0 and +90.0) I thought I could use the logic and get it sussed, but can't!

The expression I got to was:

(\d|([1-6][6-4]))|65  

Can someone please tell me where I'm misunderstanding this! And any help with the other examples above would be gratefuly received.

Community
  • 1
  • 1
Martin S
  • 211
  • 1
  • 4
  • 18
  • 1
    I think that you should indicate which language (PHP, Ruby, C#, etc) you want to use for this. Also if you compare only numbers, did you consider comparing them as normal numbers, rather than using regular expression? – Marcin Jan 26 '11 at 15:16
  • Apologies, I am using C# and and writing a web application, and the aim is to limit the entry of specific controls to a fixed range and a maximum number of decimal places. – Martin S Jan 26 '11 at 15:47

2 Answers2

8

Sorry to say this, but none of your regexes are going to work. Remember that regular expressions are designed to match textual data. While it's possible to use them to match numbers, it's not really the tool of choice.

If you have to use a regex, you need to think of the possible textual representations of a number range.

For your example 1, that would be:

  1. either a single digit
  2. or a digit between 1 and 3, followed by any digit
  3. or a 4, followed by a digit between 0 and 5.

As a regex:

^(?:\d|[1-3]\d|4[0-5])$

The ^ and $ anchors make sure that the entire string is evaluated; the (?:...) groups the alternation and "shields" it from the anchors.

For your example 3:

  1. either a 1, followed by 6-9
  2. or a 2-5, followed by any digit
  3. or a 6, followed by 0-5

As a regex:

^(?:1[6-9]|[2-5]\d|6[0-5])$

For your example 5:

  1. 1-5 digits
  2. or a 1, followed by 0-4, followed by any four digits
  3. or 150000.

As a regex:

^(?:\d{1,5}|1[0-4]\d{4}|150000)$

And so on.

Adding decimal places is not very difficult:

  • \.\d{2} works for exactly two decimal places
  • \.\d{1,3} for 1 to 3 decimal places
  • and (?:\.\d{1,2}) for 0 to 2 decimal places (and the dot is only allowed if at least one digit follows).
Tim Pietzcker
  • 328,213
  • 58
  • 503
  • 561
  • Thanks very much. I have modified some of my controls to now use range validators with the type set as integer for examples 1,3 and 5. One of the main reasons for asking was to try and understand how to limit the number of decimal places for an input, i.e. examples 2, 4 and 6 above. Thanks again. Martin – Martin S Jan 26 '11 at 15:50
  • I have added a paragraph about decimal places, too. By the way, you now have enough rep to upvote helpful answers (and you also can mark an answer as accepted). Hint, hint :) – Tim Pietzcker Jan 26 '11 at 15:55
  • Thanks, that's just what I need. I will modify the remaining controls to use regular expressions and leave the rest as range validators. Thanks again – Martin S Jan 26 '11 at 15:56
  • One other question then - how do the decima places slot into the expression? Do they just append to the end, and do they need to be inserted inside the anchors? Sorry, am just trying to do 0-10 with 1 dp and am stuck already! You'd never believe I was a developer LOL – Martin S Jan 26 '11 at 16:06
  • Yeah, append them before the anchors but outside of the `(?:...)` non-capturing parentheses: `^(?:1[6-9]|[2-5]\d|6[0-5])\.\d{1,3}$`, for example. – Tim Pietzcker Jan 26 '11 at 16:09
  • Thanks, that's what I guessed but just wanted to be sure :) – Martin S Jan 26 '11 at 16:12
  • 0 to 10 with 1 dp? ^(?:\d|10)\.\d{1}$ – Martin S Jan 26 '11 at 16:13
  • Exactly. I think you've got it :) You can drop the `{1}`, though. – Tim Pietzcker Jan 26 '11 at 16:53
  • Thanks, that's excellent. I changed it anyway as was 1 or 2 dps, but then realised I wanted the decimal places as optional so updated it to this : ^(?:\d|10)(?:\.\d{1,2})$. Appreciate your help and patience :thumbsup: – Martin S Jan 27 '11 at 09:02
  • Nearly there: `^(?:\d|10)(?:\.\d{1,2})?$` - the last `?` makes the `(?:...)` group optional. – Tim Pietzcker Jan 27 '11 at 09:06
2

The logic for 16 - 65 inclusive is 1 plus 6-9 OR 2-5 plus 0-9 OR 6 plus 0-5.

Which I think would be 1[6-9]|[2-5][0-9]|6[0-5]

Mehdi Dehghani
  • 10,970
  • 6
  • 59
  • 64