I have a requirement to handle a regular expression for no more than two of the same letters/digits in an XSL file.
This regex will do it:
^(?!.*([A-Za-z0-9])\1{2})(?=.*[a-z])(?=.*\d)[A-Za-z0-9]+$
Here's the breakdown:
(?!.*([A-Za-z0-9])\1{2})
makes sure that none of the chars repeat more than twice in a row.
(?=.*[a-z])
requires at least one lowercase letter
(?=.*\d)
requires at least one digit
[A-Za-z0-9]+
allows only letters and digits
EDIT :
removed an extraneous .*
from the negative lookahead
In response to a clarification, it seems that a single regular expression isn't strictly required. In that case I suggest you use several regular expressions or functions. My guess is, performance isn't a requirement, since usually these sorts of checks are done in response to user input. User input validation can take 100ms and still appear to be instant, and you can run a lot of code in 100ms.
For example, I personally would do a check for each of your conditions in a separate test. First, check for spaces. Second, check for at least one letter. Next, check for at least one number. Finally, look for any spans of three or more repeated characters.
Your code will be much easier to understand, and it will be much easier to modify the rules later (which, experience has shown, is almost certainly going to happen).
For example:
function do_validation(string) {
return (has_no_space(string) &&
has_no_special_char(string) &&
has_alpha(string) &&
has_digit(string) &&
! (has_repeating(string)))
I personally consider the above to be orders of magnitude easier to read than one complex regular expression. Plus, adding or removing a rule doesn't make you have to reimplement a complex regular expression (and thus, be required to re-test all possible combinations).
You may do this in 2 regexes:
/^(?=.*[a-z])(?=.*[0-9])[a-z0-9]+$/i
This will assure that there is at least 1 digit and 1 letter while accepting only letters and digits (no space or special characters)/([a-z0-9])\1{2,}/i
If this one is matched, then there is a repeated character. Which means you should throw false
.First regex:
^
: match begin of line(?=.*[a-z])
: check if there is at least one letter(?=.*[0-9])
: check if there is at least one digit[a-z0-9]+
: if the checks were true, then match only digits/letters one or more times$
: match end of linei
: modifier, match case insensitiveSecond regex:
([a-z0-9])
: match and group a digit or a letter\1{2,}
: match group 1 two or more timesi
: modifier, match case insensitiveFor matching the same character repeated 3 or more times consecutively, try:
([a-zA-Z0-9])\1{2,}
Sample matches (tested both here and here): AABBAA
(no matches), AABBBAAA
(matches BBB
and AAA
), ABABABABABABABA
(no matches), ABCCCCCCCCCC
(matches CCCCCCCCCC
).
Does this one work for you?
/(\b(?:([A-Za-z0-9])(?!\2{2}))+\b)/
Try it out:
var regex = new RegExp(/(\b(?:([A-Za-z0-9])(?!\2{2}))+\b)/)
var tests = ['A1D3E', 'AAAA', 'AABAA', 'abccddeeff', 'abbbc', '1234']
for(test in tests) {
console.log(tests[test] + ' - ' + Boolean(tests[test].match(regex)))
}
Will output:
A1D3E - true
AAAA - false
AABAA - true
abccddeeff - true
abbbc - false
1234 - true