tags:

views:

1052

answers:

6

It should match all the following examples.

aBCd22
a2b2CD
22aBcD
+1  A: 

I don't know if you can do it with only one regular expression, but you can certainly do it with two. That said it seems a bit excessive to be using regex for this task.

In Perl, I would do:

m/\d.*\d/ # match exactly 2 numeric characters
  &&
m/(?:[[:alpha:]].*){4}/ # match exactly 4 alpha characters
1800 INFORMATION
Very clever. You might also need checks for the length as well?
Douglas Leeder
Your \d.*\d idea gave me inspiration for my own answer. Thanks. =]
strager
Your matches aren't anchored, so again, they only check that *at least* two digits and four alphas exist somewhere in the string.
hobbs
+1  A: 

I don't think regex is the way to go here.

Sure, you could create an alternation of every possible allowed order of digits and letters, but you'd need 6 * 5 = 30 of them.

I don't know any way of doing the counting you want with regex.

You could have a regex to check you have 6 alpha-numeric characters, then do the counting manually.

Douglas Leeder
A: 

Maybe this?

(?=[a-z]*\d?[a-z]*\d?)
(?![a-z]*\d[a-z]*\d[a-z]*\d)
(?=\d*[a-z]?\d*[a-z]?\d*[a-z]?\d*[a-z]?)
(?!\d*[a-z]\d*[a-z]\d*[a-z]\d*[a-z]\d*[a-z])
[\da-z]{2,6}

It works by making sure the selection has zero, one, or two digits (first lookahead), but doesn't have more than two (second lookahead). Similarly, it checks for zero to four letters (third lookahead) but not more than four (fourth lookahead). The fifth line matches one to six characters.

If you want to match words only, wrap it in \b.

EDIT: Now you added a requirement for the length of the match to be six characters. Only a slight modification is needed:

(?=[a-z]*\d[a-z]*\d)
(?![a-z]*\d[a-z]*\d[a-z]*\d)
(?=\d*[a-z]\d*[a-z]\d*[a-z]\d*[a-z])
(?!\d*[a-z]\d*[a-z]\d*[a-z]\d*[a-z]\d*[a-z])
[\da-z]{6}
strager
well, it should match these examples aBCd22 a2b2CD 22aBcD abcd22
@kurozakura: According to this site, mine do: http://derekslager.com/blog/posts/2007/09/a-better-dotnet-regular-expression-tester.ashx
strager
Thanks :)
A: 

This regular expression should do it:

^(?=[a-zA-Z]*\d[a-zA-Z]*\d[a-zA-Z]*$)(?=\d*[a-zA-Z]\d*[a-zA-Z]\d*[a-zA-Z]\d*[a-zA-Z]\d*$).*

Or more compact:

^(?=[a-zA-Z]*(?:\d[a-zA-Z]*){2}$)(?=\d*(?:[a-zA-Z]\d*){4}$).*
Gumbo
Heh, that looks a lot like mine. =]
strager
+4  A: 

A compact version, using the positive lookahead operator:

^(?=(.*[0-9]){2})(?=(.*[A-Za-z]){4})[A-Za-z0-9]{6}$

Explanation:

(?=(.*[0-9]){2}) # asserts that you have 2 digits
(?=(.*[A-Za-z]){4}) # asserts that you have 4 characters
[A-Za-z0-9]{6} # does the actual matching of exactly 6 alphanumeric characters

A simple test case, in Python:

import re
rex = re.compile('(?=(.*[0-9]){2})(?=(.*[A-Za-z]){4})[A-Za-z0-9]{6}')
tests = ['aBCd22', 'a2b2CD', '22aBcD', 'asd2as', '', '201ABC', 'abcA213']
for test in tests:
print "'%s' %s" % 
       (test, "matched" if rex.match(test) != None else "didn't match")

Output:

'aBCd22' matched
'a2b2CD' matched
'22aBcD' matched
'asdas' didn't match
'' didn't match
'201ABC' didn't match
'abcA213' didn't match
JG
Clean, simple, and effective.
Rob Elliott
Actually, this only checks that there are at *least* two digits and at *least* four letters. It works regardless, because you can't have anything more than 2 digits + 4 letters and come up with exactly six characters, but as far as explanations go... :)
hobbs
a working regex fragment for validating exactly `x` digits and `y` letters would be like: `/^(?=([^0-9]*[0-9]){x}$)(?=([^A-Za-z]*[A-Za-z]){y}$)/` but if you ask me the whole idea is excessively clever. If you *have* to do it to work with some tool that only accepts a regex for validation, okay. But if you don't need to do it, then say what you mean instead. :)
hobbs
Thanks thats exactly what i needed
Suppose if i wanted it to match in the case of 'a1' or 'a11' or 'ab11' how would u put the range for [A-Za-z0-9]{6} if u make it [A-za-z0-9]{1,6} and for the assertion of the digits with (?=(.*[0-9]){1,2}) it still accepts 'a111'
A: 
^((?<digit>\d)|(?<alpha>[a-zA-Z])){6}
(?<-alpha>){4}(?(alpha)(?!))
(?<-digit>){2}(?(digit)(?!))$

This will match 6 characters with exactly 2 digits and 4 letters. It does this by grabbing whatever it can then counting the results by popping them off the counter stack. Check this link for more details.

  • (?<-alpha>){4} means 'pop 4 matches off the stack'. If it cannot pop, it fails
  • (?(alpha)(?!)) means 'if there is an alpha match, look for (?!), which always fails.
  • ^ and $ match the beginning and ending
Rob Elliott