The challenge
You need to write regex that will validate a password to make sure it meets the following criteria:
- At least six characters long
- contains a lowercase letter
- contains an uppercase letter
- contains a number
Valid passwords will only be alphanumeric characters.
The solution in Python code
Option 1:
from re import compile, VERBOSE
regex = compile("""
^ # begin word
(?=.*?[a-z]) # at least one lowercase letter
(?=.*?[A-Z]) # at least one uppercase letter
(?=.*?[0-9]) # at least one number
[A-Za-z\d] # only alphanumeric
{6,} # at least 6 characters long
$ # end word
""", VERBOSE)
Option 2:
import re
regex = re.compile(r"""
(?=^[a-zA-Z0-9]{6,}$)
(?=\w*[a-z])
(?=\w*[A-Z])
(?=\w*\d)
""", re.X)
Option 3:
regex="^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)[^\W_]{6,}$"
Test cases to validate our solution
from re import search
test.describe("Basic tests")
test.assert_equals(bool(search(regex, 'fjd3IR9')), True)
test.assert_equals(bool(search(regex, 'ghdfj32')), False)
test.assert_equals(bool(search(regex, 'DSJKHD23')), False)
test.assert_equals(bool(search(regex, 'dsF43')), False)
test.assert_equals(bool(search(regex, '4fdg5Fj3')), True)
test.assert_equals(bool(search(regex, 'DHSJdhjsU')), False)
test.assert_equals(bool(search(regex, 'fjd3IR9.;')), False)
test.assert_equals(bool(search(regex, 'fjd3 IR9')), False)
test.assert_equals(bool(search(regex, 'djI38D55')), True)
test.assert_equals(bool(search(regex, 'a2.d412')), False)
test.assert_equals(bool(search(regex, 'JHD5FJ53')), False)
test.assert_equals(bool(search(regex, '!fdjn345')), False)
test.assert_equals(bool(search(regex, 'jfkdfj3j')), False)
test.assert_equals(bool(search(regex, '123')), False)
test.assert_equals(bool(search(regex, 'abc')), False)
test.assert_equals(bool(search(regex, '123abcABC')), True)
test.assert_equals(bool(search(regex, 'ABC123abc')), True)
test.assert_equals(bool(search(regex, 'Password123')), True)
test.describe("Random tests")
from random import random, randint
sol=r"^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)[a-zA-Z\d]{6,}$"
lower="abcdefghijklmnopqrstuvwxyz"
upper="ABCDEFGHIJKLMNOPQRSTUVWXYZ"
digits="0123456789"
all="".join([lower,upper,digits])
wrong=" !_+-?/\\"
for _ in range(100):
s="".join(sorted([upper[randint(0,len(upper)-1)], lower[randint(0,len(lower)-1)], digits[randint(0,len(digits)-1)]]+[all[randint(0,len(all)-1)] if randint(0,10) else wrong[randint(0,len(wrong)-1)] for q in range(randint(0,15))], key=lambda a: random()))
test.it("Testing for "+repr(s))
test.assert_equals(search(regex,s)!=None, search(sol,s)!=None, "It should work for random inputs too")