views:

599

answers:

5

I need to enforace the following regex, and I'm horrible at writing these:

  xx12ab - valid
  x12345 - invalid
  xxxxx1 - invalid
  xxx123 - valid

I need to have a 6 character string that HAS TO HAVE at least 2 alpha chars, and 2 numeric chars, limited to only alpha/numeric in the string.

Thanks.

A: 

Do you need to use regular expressions? If you do, I don't think you'll get around having to write every permutation of how the characters could be ordered, i.e. /[a-zA-Z][a-zA-Z][0-9][0-9]\w\w|[a-zA-Z][0-9]\w[a-zA-Z][0-9]\w|.../

Unless someone else can think of something clever.

sepp2k
A: 

You may wish to look up regex "lookahead". I've only had to use it once and am therefore by no means an expert, but it may help you accomplish what you're reaching for.

+6  A: 

The easiest way of doing it would be to observe that if all the characters are alphanumeric (as they should be), an invalid string is one that has either 5 numbers or 5 letters.

That makes the algorithm very simple. In pseudocode (because you didn't mention your language):

int numcount = 0, alphacount = 0
foreach (char c : string)
    if c is numeric
        numcount++
    else if c is alpha
        alphacount++
    else
        return false // invalid character
if numcount >= 5 || alphacount >= 5
    return false
if numcount + alphacount != 6
    return false
return true
Michael Myers
+3  A: 

I'd recommend using three seperate regexps, one to enforce 6 all alphanumeric, one to enforce at least two digits, one to enforce at least two letters.

Regexps vary between languages, but in perl they would look something like this:


/^\w{6}$/
/\d.*\d/
/[a-zA-Z].*[a-zA-Z]/

Edit: Now that I know about lookahead, this works:

/(?=(.*[0-9]){2})(?=(.*[a-zA-Z]){2})^[0-9a-zA-Z]{6}$/
Beta
And don't use a regexp to check the length of the string, just use `length`/`strlen`/whatever directly.
Dave Hinton
+1 for the final regular expression. Note that because lookarounds don't capture, the result of a match will a blank string.
Daniel Vandersluis
You're right.. and when I fix it the result is a little shorter and simpler! Thanks!
Beta
+1  A: 

If you must use a single expression you can write it.

assuming upper and lower case.

(?!^[0-9]*[a-zA-Z][0-9]*$)(?!^[a-zA-Z]*[0-9][a-zA-Z]*$)^([a-zA-Z0-9]{6})$

This says:

(?!^[0-9]*[a-zA-Z][0-9]*$)

don't match if there is only a single letter

(?!^[a-zA-Z]*[0-9][a-zA-Z]*$)

don't match if there is only a single digit

^([a-zA-Z0-9]{6})$

do match if there is six digits/letters

Simeon Pilgrim