tags:

views:

214

answers:

8

I have this simple regex,

[\d]{1,5}

that matches any integer between 0 and 99999.

How would I modify it so that it didn't match 0, but matches 01 and 10, etc?

I know there is a way to do an OR like so...

[\d]{1,5}|[^0]{1}

(doesn't make much sense)

There a way to do an AND?

+2  A: 

My vote is to keep the regex simple and do that as a separate compare outside the regex. If the regex passes, convert it to an int and make sure the converted value is > 0.

But I know that sometimes one regex in a config file or validation property on a control is all you get.

Joel Coehoorn
+5  A: 

probably better off with something like:

0*[1-9]+[\d]{0,4}

If I'm right that translates to "zero or more zeros followed by at least one of the characters included in '1-9' and then up to 4 trailing decimal characters"

Mike

mjmarsh
Your expression would not match "10".
Kena
you're right, I've updated to be more accurate. Thanks
mjmarsh
Your expression also matches 00. It isn't explicitly denied, but i'm not sure if that is the intent.
Rontologist
Changing the start of the regex from 0* to 0? would limit it to only allow 0 or 1 leading zeroes, preventing 007 from matching. Note, however, that any leading zero(es) will not be counted in the 5-digit limit, which may or may not be desirable.
Dave Sherohman
I think you need to drop the '+' sign after the [1-9], otherwise you will match more than 5 digits - eg 1110123 would be matched. See Chris Marasti-Georg for a good format.
Hamish Downer
+2  A: 

How about an OR between single digit numbers you will accept and multiple-digit numbers:

^[1-9]$|^\d{2,5}$

andy
That would still match 00, which does not seem to be the poster's goal
Chris Marasti-Georg
The second part could be [1-9]\d{1,4} if you wanted to disallow "00000".
andy
That wouldn't match 01
Chris Marasti-Georg
Could add 0{0,4} to the front of both expressions to allow leading zeros, but of course that might allow too many digits :-)
andy
You also need to allow 101 through...
Jonathan Leffler
Unless I'm missing something, 101 is no problem (note I said 0{0,4} so that allows no leading zeros)
andy
+3  A: 

I think the simplest way would be:

[1-9]\d{0,4}

throw that between a ^$ if it makes sense in your case, and if so, add a 0* to the beginning:

^0*[1-9]\d{0,4}$
Chris Marasti-Georg
It won't limit the string to 5 characters, but is otherwise good.
Joel Coehoorn
true - luckily, he didn't say he was limiting to 5 characters. He just said he wanted 1-99999
Chris Marasti-Georg
+1  A: 

By using look-aheads you can achieve the effect of AND.

^(?=regex1)(?=regex2)(?=regex3).*

Though there is a bug in Internet Explorer, that sometimes doesn't treat (?= ) as zero-width.

http://blog.stevenlevithan.com/archives/regex-lookahead-bug

In your case:

^(?=\d{1,5}$)(?=.*?[1-9]).*
MizardX
A: 
^([1-9][0-9]{0,4}|[0-9]{,1}[1-9][0-9]{,3}|[0-9]{,2}[1-9][0-9]{,2}|[0-9]{,3}[1-9][0-9]|[0-9]{,4}[1-9])$

Not pretty, but it should work. This is more of a brute force approach. There's a better way to do it via grouping as well, but I'm drawing a blank on the actual implementation at the moment.

Joel Coehoorn
+1  A: 

It looks like you are searching for 2 different conditions. Why not break it out to 2 expressions? It might be simpler and more readable.

var str = user_string;
if ('0' != str && str.matches(/^\d{1,5}$/) {
    // code for match
}

or the following if a string of 0's is not valid as well

var str = user_string;
if (!str.matches(/^0+$/) && str.matches(/^\d{1,5}$/) {
    // code for match
}

Just because you can do it all in one regex doesn't mean that you should.

Rontologist
The 2nd regex would be better as a simple if condition. Once you know that it's numeric, you can just convert to an int and check that this int is > 0.
Joel Coehoorn
+2  A: 

I think a negative lookahead would work. Try this:

#!/bin/perl -w

while (<>)
{
    chomp;
    print "OK: $_\n" if m/^(?!0+$)\d{1,6}$/;
}

Example trace:

0
00
000
0000
00000
000000
0000001
000001
OK: 000001
101
OK: 101
01
OK: 01
00001
OK: 00001
1000
OK: 1000
101
OK: 101
Jonathan Leffler