How do you write a regular expression that matches a numeric range from 0 or 000 to 180 ?
I don't think regex is the right choice for this. Have you tried parsing the value? If you have to use regex I would match \d{1,3}
parse the string and then validate the number in code.
The easiest way for this would be to parse the string as a number and look for the number to be in the proper range.
To do this with pure regex you need to identify the pattern and write it out:
^(0?[0-9]{1,2}|1[0-7][0-9]|180)$
This has three alternatives: one for single- and two-digit numbers (allowing leading zeroes), where each digit can be anything from 0 to 9. And another one that specifies what range of digits is allowed for each digit in a three-digit number. In this case, this means that the first digit needs to be 1, the second between 0 and 7 and the last one may be anything. The third alternative is just for the number 180 which didn't fit nicely into the pattern elsewhere.
A more straightforward approach might be
^(0{0,2}[0-9]|0?[1-9][0-9]|1[0-7][0-9]|180)$
which just alternates for each tricky numeric range there might be.
I modified Gumbo's:
^(00?0?|0?[1-9][0-9]?|1[0-7][0-9]|180)$
Try that.
if you don't care about negative numbers
>> r = /\b(0?\d?\d|1[0-7]\d|180)\b/
=> /\b(0?\d?\d|1[0-7]\d|180)\b/
>> (0..200).map {|i| i.to_s =~ r }
=> [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil]
>>
There is an online utility to generate these at UtilityMill.com For your question, this returns:
0*([0-9]{1,2}|1[0-7][0-9]|180)
I would break down the ranges so that it can easily be specified in separate individual regex:
^(0|0[0-9][0-9]|1[0-7][0-9]|180)$
Or, what's the same in human readable terms:
0 000-099 100-179 180
If you need the two digit range, it's just a matter of adding [0-9][0-9]
to the regex.
Also, if you are having trouble working with regex, try to specify them in a manner that makes the regex operators as clear as possible - usually there's a way to represent them in a way that makes their function much more clear, specially if the language you are doing this in allows you to separate portions of the regex specification into separate columns and lines..
My two cents:
Anyone posting an answer to this question should have tested their regex with AT LEAST the following inputs:
Should match: 0, 00, 000, 5, 05, 005, 95, 095, 180
Should NOT match: 0000, 0095, 181, 190
I think what Johannes Rössel wrote is about as good as you'll get:
^(0?[0-9]{1,2}|1[0-7][0-9]|180)$