Using Regex to match if a specific character occurs a specific number of times

Viewed 397

I'm trying to use regular expressions to check if a string, str, contains at least two numbers and exactly two of any of the following symbols: '!','@','#','$','%','&','*'.

What seems to be happening is that I'm only matching if they occur consecutively and not in total. How do I fix this?

str = 'a1b2c$3d#4e!f@ghi0'

sym = '[!@#$%&*]{2}'
num = '[0-9]{2,}'

for char in str:
    if re.search(sym, str):
        if re.search(num, str):
            print('match!')
        else:
            print('no matches!')
1 Answers

If you want to use 2 patterns, you don't have to loop to check every character. In sym You can check if the string has exactly 2 of the listed characters.

In num you can match at least 2 digits.

import re

str = 'test$test$test123'

sym = r'^[^!@#$%&*\r\n]*[!@#$%&*][^!@#$%&*\r\n]*[!@#$%&*][^!@#$%&*\r\n]*\Z'
num = r'^[^\d\r\n]*\d[^\d\r\n]*\d'

if re.search(sym, str) and re.search(num, str):
    print('match!')
else:
    print('no matches!')

You might also use a single pattern with re.match

^(?=[^\d\r\n]*\d[^\d\r\n]*\d)[^!@#$%&*\r\n]*[!@#$%&*][^!@#$%&*\r\n]*[!@#$%&*][^!@#$%&*\r\n]*\Z

Explanation

  • ^ Start of string
  • (?=[^\d\r\n]*\d[^\d\r\n]*\d) Positive lookahead, assert 2 digits
  • [^!@#$%&*\r\n]*[!@#$%&*][^!@#$%&*\r\n]*[!@#$%&*][^!@#$%&*\r\n]* Match exactly 2 of any of the listed characters
  • \Z End of string

Regex demo | Python demo

import re

str = 'test$test$test123'
pattern = r'(?=[^\d\r\n]*\d[^\d\r\n]*\d)[^!@#$%&*\r\n]*[!@#$%&*][^!@#$%&*\r\n]*[!@#$%&*][^!@#$%&*\r\n]*\Z'
if re.match(pattern, str):
    print('match!')
else:
    print('no matches!')

Without using a regex, one option is to count the occurrences of a digit and special chars:

s = 'test$test$test123'
specialChars = "!@#$%&*"
num = 0
sym = 0

for char in s:
    if char.isdigit():
        num += 1
    if char in specialChars:
        sym += 1

if num > 1 and sym == 2:
    print("Match")

Python demo

Related