- Max Length of the String is 6.
- The string should contain at most 2 digits
- The string should contain at most 4 alphabets
So the following examples should match
abcd22
a1cd3d
11acde
a1c
1ad
So the following examples should match
abcd22
a1cd3d
11acde
a1c
1ad
Regexes are not good at keeping track of state. You could do this with a regex, but it would be much easier to use a simple calculator and small regexes program:
bool IsValid(string s)
{
int numInts = 0;
int numChars = 0;
Regex isDigit = new Regex(@"\d");
Regex isChar = new Regex(@"[a-zA-Z]"); // NOTE: will NOT catch non english letters
if (s.Length() <= 6)
{
return false;
}
foreach (char c in s)
{
if (isDigit.IsMatch(c))
{
++numInts;
}
if (isChar.IsMatch(c))
{
++numChars;
}
}
return numInts == 2 && numChars == 4;
}
Constify / rename args to meet your needs.
Of course, if you want to be very C like, you could do a numeric comparison on the char, but that will even further take you away from a solid, robust solution.
What you want isn’t really possible in regular expressions because regular expressions can’t count, which would be required here. In fact, regular expressions seem to be able to count characters in direct sequence, e.g. in this case:
/x{2,3}/ # 2 or 3 ‘x’s
… but that’s actually not counting, because it’s just a shortcut for this expression:
/xxx?/
i.e. 2 x
’s, followed by an optional third one.
Your expression, on the other hand, would have to keep track of two different counters over the whole automaton which represents the expression. That’s simply not possible in classical regular expressions (and still very hard using more modern incarnations of regular expressions which use pushdown automata to save states).
I'd do an OR test of a bunch of regexes:
/^[a-z0-9]{0,6}$/ # at most 6 characters
/([a-z].*){5}/ # more than 4 letters
/(\d.*){3}/ # more than 2 digits
So:
if ( /^[a-z0-9]{0,6}$/ and !( /([a-z].*){5}/ or /(\d.*){3}/ ) ) {
print "valid";
}
I would not use regex for this one, except maybe to check for alphanumeric/less than 6: /^[0-9a-z]{1,6}$/i
. But the count conditions, while technically doable using regexes, are done better with simple counting.
So i would
/^[0-9a-z]{1,6}$/i
You could do this using negative lookaheads.
(?!\d{5})(?![a-z]{3})[a-z0-9]{1,6}
(?!\d{5})
fails if 5 or more digits are found
(?![a-z]{3})
fails if 3 or more characters are found
If both of those pass, we finally verify that there are between 1 and 6 alphanumeric characters with (?!\d{5})(?![a-z]{3})[a-z0-9]{1,6}