0

I am trying to create a regular expression for accepting strings of 8 characters composed of both letters and numbers, and not only letters or numbers.

The regex '^[A-Z0-9]{8}$' is not enough as it allows words like 'ABCDEFGH' or '12345678'. How do I create a regex to only accept 8 character strings containing both capital letters AND numbers like 'AB123C7Q'?

ramez
  • 321
  • 3
  • 22

2 Answers2

4

You need to add 2 conditions (assertions) in your regex in the form of lookahead:

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

There are 2 lookahead assertions being used here:

  • (?=.*[a-zA-Z]): Asserts that we have at a letter ahead
  • (?=.*\d): Asserts that we have at last a digit ahead
anubhava
  • 761,203
  • 64
  • 569
  • 643
0

The following is an alternative for Python community presenting a much faster pythonic solution using builtin str.isalnum and str.isdigit functions:

Custom function called checkalnum ("check if string contains alphanumeric"):

def checkalnum(test_str: str):
    if not test_str.isalnum() or len(test_str) != 8:
        return False

    has_digit, has_letter = False, False
    for c in test_str:
        if c.isdigit(): has_digit = True
        else: has_letter = True

        if has_digit and has_letter:
            return True
    return False

Time performance comparison (in IPython session):

In [811]: test_str = 'AB123C7Q'

In [812]: %timeit re.search(r'^(?=.*[a-zA-Z])(?=.*\d)[a-zA-Z\d]{8}$', test_str)
1.88 µs ± 284 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)

In [813]: %timeit checkalnum(test_str)
992 ns ± 87.5 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)

In [814]: 
RomanPerekhrest
  • 88,541
  • 4
  • 65
  • 105