views:

844

answers:

8

I have a field on a form that takes the following values: -1, 2-10, 99

I have a business rule that's concerned with answers 2-10.

I'm trying to write a regular expression that will match 2-10 but not 99, and I'm having trouble.

The original expression:

^2|3|4|5|6|7|8|9|10$

Fails because 99 is matched (technically, twice). Also, the Line boundries are something I've never been comfortable with. I oberve different behavior from them in expresso than I do in other places (e.g. .net). In this particular instance, the regex is being run in javascript. Anyway, expresso seems to ignore them (and if I put the values in brackets:

^[2|3|4|5|6|7|8|9|10]$

^[2-9]$

either "all spelled out" or as a range, expresso never returns any matches if I specify the opening line/string closing line/string characters (and yes, I was trying to match the 10 separately in the second case there).

I know, I know. If you use a regex to solve a problem, then you have two problems (and presumably they'll start inviting friends over, thing 1 and thing 2 style). I don't have to use one here; I may switch to a case statement. But it seems like I should be able to use a regex here, and it seems a reasonable thing to do. I'm still pretty green when it comes to the regex;

+7  A: 

Use parentheses around the alternations, since concatenation has higher precedence than alternation:

^(2|3|4|5|6|7|8|9|10)$
Adam Rosenfield
Or for a more compact form ^([2-9]|10)$
Martin Brown
So why doesn't this match anything in Expresso? I've got numeric values liberally inserted into the sample text window, but get no matches? There must be some setting I need to tweak, but Expresso threw me off here.
peacedog
@Martin - you missed a trick there, seeing soulmerges answer :)
annakata
@peacedog - the code you posted has [ not (, which completely changes the meaning
annakata
@annakata - I get that, but I'm talking about Adam's answer. It doesn't work in Expresso for me.
peacedog
A: 

The reason your original expression fails is because you're matching ^2, 3, 4, 5, 6, 7, 8, 9, 10$.

Try this regex: ^(2|3|4|5|6|7|8|9|10)$

gms8994
A: 

I found this site to be very helpful when dealing and testing with RegEx: here.

CheGueVerra
+44  A: 

This is clearly a case where you shouldn't use RegExp but numerical evaluation:

num = parseInt(aNumber, 10)
if (num >= 2 && num <= 10) {
    alert("Match found!")
}
Georg
parseInt(aNumber,10) // Don't forget the radix or you can be surprised.
some
well played, sir. Well played.
Learning
While i do agree this would be a far superior solution to regexes in most cases, an even better solution would be to constrain the input by means of UI (dropdownlist anyone?). However, the question is specifically about a regualar expression.
Kris
Just because the question is about a regular expression doesn't mean the right answer is a well-formed regex. http://weblogs.asp.net/alex_papadimoulis/archive/2005/05/25/408925.aspx
Randy
The problem with constraining is that the input-ui has also to accept -1 and 99, therefore this wouldn't work. It's about extracting data later.
Georg
the second argument to parseInt() isn't really necessary, there are no zeros in the field except the one in the number 10. Yet it's still better to be on the safe side.
Georg
@ Kris - dropdowns don't stop people from submitting any value to the server. @ gs - actually, since this is user input that's being parsed, I would consider the radix to be required here. You can never know what they'll enter.
Peter Bailey
@BaileyP, I never said don't do server side validation!
Kris
That's not unreasonable though I was really more curious about making the regex work, and I should have been clearer on that. Also, no, drop down is not an option.
peacedog
My solution has nothing to do with drop downs, it's about choosing the right technic.
Georg
+18  A: 

You need parantheses for that. I would further use ranges to keep things readable:

^([2-9]|10)$
soulmerge
+1 much more concise
annakata
"^" and "$" should both be replaced by "\b". The meaning would be the same, but you can then globally apply it to a complete string.
Tomalak
A: 

Why not a pattern that covers all your cases?

^(?:-1|[2-9]|10|99)$
Peter Bailey
+1  A: 

A complete javascript function to match either 2 though 9, or 10

<script type="text/javascript">
    function validateValue( theValue )
    {
     if( theValue.match( /^([2-9]{1}|10)$/ ) )
     {
      window.alert( 'Valid' );
     }
     else
     {
      window.alert( 'invalid' );
     }
     return false;
    }
</script>

The regex is easily expanded to incorporate all of your rules:

/^(-1|[2-9]|10|99)$/ // will match -1, 2-10, 99

edit: I forgot to mention you'll have to substitute your own true/false situational logic. edit2: added missing parenthesis to 2nd regex.

Kris
Wrong. /^-1|[2-9]|10|99$/ will match -1 at the beginning of the string, or a 2,3,4,5,6,7,8,9 anywhere, or a 10 anywhere, or 99 at the end of the string. Perhaps you meant: /^(-1|[2-9]|10|99)$/ (and your first regexp is wrong too)
some
I just found out my testcases were not extensive enough and that makes you correct on both counts. I have adapted the snippet.
Kris
A: 

This online utility is very good at generating re's for numeric ranges: http://utilitymill.com/utility/Regex_For_Range. For the range 2-10 inclusive, it gives this expression: \b0*([2-9]|10)\b. If you want to omit leading 0's, take out the "0*" part.

Paul McGuire