Skip to content
Advertisement

Validate card numbers using regex python

I have some credit card numbers with me and want to validate them over the below rules.

► It must only consist of digits (0-9)

► It may have digits in groups of 4, separated by one hyphen “-“

► It must NOT have 4 or more consecutive repeated digits

► It may contain exactly digits without any spaces

Input:

  • 5123-4567-8912-3456

  • 61234-567-8912-3456

  • 4123356789123456

  • 5133-3367-8912-3456

Output:

  • Valid

  • Invalid (because the card number is not divided into equal groups of 4)

  • Valid

  • Invalid (consecutive 33 33digits is repeating 4 times)

I have tried here and it works only if i include hyphen at the end. Can somebody give me a correct reg ex for it.

Edit:

Regex Code: ([0-9]{4}-){4}

Input to be matched 6244-5567-8912-3458

It doesn’t match until I put hyphen at the end.

Edit

import re
import itertools
text="5133-3367-8912-3456"
print(len(text))

l=[(k, sum(1 for i in g)) for k,g in itertools.groupby(text)]  #To calculate frequency of characters and later we can filter it with the condition v<=3 for checking the concurrency condition

if re.search(r'^[456]+',text) and len(text)==16  and re.search(r'[d]',text) and all(v<=3 for k,v in l) and bool(re.search(r's',text)) is False and bool(re.search(r'[a-z]',text)) is False or( bool(re.search(r'-',text))is True and len(text)==19) :
    print("it passed")

else :
    print("False")

Advertisement

Answer

Your regex is almost correct. It asks for four dash terminated groups of numbers. What you want is three dash-terminated groups, followed by a non-dash-terminated group, or a single blob with no dashes:

(?:[0-9]{4}-){3}[0-9]{4}|[0-9]{16}

[Link]

I made the group non-capturing since you don’t need to capture the contents. You can also use d instead of [0-9]:

(?:d{4}-?){3}d{4}

[Link]

The validation of consecutive numbers is probably easier to do in a separate step. Once the regex match passes, remove all the dashes:

num = num.replace('-', '')

Now check for repeated digits using itertools.groupby, something like in this question/answer:

from itertools import groupby

if max(len(list(g)) for _, g in groupby(num)) >= 4:
    print('Invalid: too many repeated digits')

Full Code

from itertools import groupby
import re

pattern = re.compile(r'(?:d{4}-){3}d{4}|d{16}')

def count_consecutive(num):
    return max(len(list(g)) for _, g in groupby(num)

num = '6244-5567-8912-3458'
if not pattern.fullmatch(num) or count_consecutive(num.replace('-', '')) >= 4:
    print('Failed')
else:
   print('Success')
User contributions licensed under: CC BY-SA
6 People found this is helpful
Advertisement