1

I have a generated code within an email that I need to match. It will always be 6 characters long and must contain a minimum of one number and one letter. The order of numbers and letters will vary each time. I'm really new to regex.

Here is a few examples of codes I have received that I need to pull from the body of an email:

q295zp
gd5z9r
ktsft5
mz3jr4

I have tried these and countless more but continue to match the codes above as well as 6 letter words.

[a-z1-9]{6}

([a-z]+[1-9]+){6}

How do I make it only match 6 letter sequences that have at least one letter and one number?

Wiktor Stribiżew
  • 607,720
  • 39
  • 448
  • 563
Steve
  • 27
  • 3
  • 1
    Have you tried solving this without regular expressions? – mkrieger1 Nov 06 '20 at 18:16
  • @mkrieger1 I have not tried solving this without regular expressions and honestly the thought didn't cross my mind. I'm also very new to any programming and am not sure how I would even begin to solve this without regular expressions. – Steve Nov 06 '20 at 18:47
  • 1
    The suggestion given above uses two "lookahead" expressions "(?=.*\d)" and "(?=.*[a-zA-Z])" to make sure that the matched expression "[a-zA-Z\d]{6}" includes at least one digit and one letter. See https://www.rexegg.com/regex-disambiguation.html#lookarounds for information about "lookarounds". – technomage Nov 06 '20 at 19:00

3 Answers3

3

This is so not appropriate to regular expressions and so simple in actual python that I'm not even trying the former.

def f(string):
    digits = sum(map(str.isdigit, string))
    alphas = sum(map(str.isalpha, string))
    return len(string) == 6 and digits >= 1 and alphas >= 1

truthy_suite = [
    'q295zp',
    'gd5z9r',
    'ktsft5',
    'mz3jr4',
]

falsy_suite = [
    'qwerty',
    '123456',
]

for test in truthy_suite:
    assert f(test)

for test in falsy_suite:
    assert not f(test)

Check it at colab.google.com

Pedro Rodrigues
  • 2,520
  • 2
  • 27
  • 26
3

Could you please try following. Written and tested in link https://regex101.com/r/tux72m/2

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

Explanation:

  • ^(?=.*\d): Checking from starting and ?= looking ahead and matching digit.
  • (?=.*[a-zA-Z]): Using lookahead to check 1 small/capital letter.
  • [a-zA-Z\d]{6}$: From starting to end it should match either letters(small/capital) OR digits in number 6.
RavinderSingh13
  • 130,504
  • 14
  • 57
  • 93
1

For completion, here's another approach without using re

def match(s):
    return any(_s.isalpha() for _s in s) and any(_s.isdigit() for _s in s)

If you want exactly 6 digits as well,

def match(s):
    return len(s) == 6 and any(_s.isalpha() for _s in s) and any(_s.isdigit() for _s in s)
Teshan Shanuka J
  • 1,448
  • 2
  • 17
  • 31