Search code examples
python-3.xregexvalidationpython-re

Regular expression to match an UID


I'm trying to validate an UID which has the following rules

  1. It must contain at least 2 uppercase English alphabet characters.
  2. It must contain at least 3 digits (0-9).
  3. It should only contain alphanumeric characters.
  4. No character should repeat.
  5. There must be exactly 10 characters in a valid UID.

I have tried it doing by regular expression but I'm unable to create a pattern which can satisfy all the rules.

So I did it without the regular expression.

#import re
#pattern = r'^[A-Z0-9]{10}$'

testCases = int(input())

for _ in range(testCases):
    uid = input()
    if len(uid) == 10 and len(uid) == len(set(uid)):
       countChr = countNum = 0
       for i in uid:
           if i.isdigit():
               countNum += 1
           elif i.isalpha():
               countChr +=1
       if countChr >= 2 and countNum >= 3:
           print("Valid")
       else:
           print("Invalid")
   else:
       print("Invalid")

The above program worked perfectly but I want to validate the UID with regular expression, so is there any pattern which can satisfy all the given rules?


Solution

  • Try this regex:

    ^(?=(?:.*[A-Z]){2})(?=(?:.*[0-9]){3})(?:([a-zA-Z0-9])(?!.*\1)){10}$
    
    ^                           beginning of the text
    
        (?=                     positive lookahead
            (?:                 non-capturing group
                .*[A-Z]         anything followed by an uppercased letter
            ){2}                match 2 of them
        )                       end of the lookahead
    
        (?=                     positive lookahead
            (?:                 non-capturing group
                .*[0-9]         anything followed by a digit
            ){3}                match 3 of them
        )                       end of the lookahead
    
        (?:                     non-capturing group
            ([a-zA-Z0-9])       any alphanumeric character and put it in group 1
            (?!.*\1)            negative lookahead, make sure there's no repeated character ahead
        ){10}                   match 10 of them
        
    $                           end of the text
    

    Check the test cases

    Using python

    import re
    
    pattern = r'^(?=(?:.*[A-Z]){2})(?=(?:.*[0-9]){3})(?:([a-zA-Z0-9])(?!.*\1)){10}$'
    testCases = int(input())
    
    for _ in range(testCases):
        uid = input()
        if re.match(pattern, uid):
            print("Valid")
        else:
            print("Invalid")