我有一些信用卡号码,并希望通过以下规则对其进行验证。
►必须只包含数字(0-9)
►它可能包含4个数字的数字,用一个连字符“ - ”
分隔►不得有4个或更多连续重复的数字
►它可能包含没有任何空格的数字
输入:
5123-4567-8912-3456
61234-567-8912-3456
4123356789123456
5133-3367-8912-3456
输出:
有效
无效(因为卡号未分为4组相等的组)
有效
无效(连续33 33个数字重复4次)
我已经尝试here并且只有在最后包含连字符时它才有效。有人可以给我一个正确的注册表。
修改
正则表达式代码:([0-9]{4}-){4}
要匹配的输入6244-5567-8912-3458
直到我把连字符放在最后才匹配。
修改
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")
答案 0 :(得分:6)
我的解决方案有两步逻辑。你不能一气呵成的原因,与python的限制有关。我们将保存以供日后使用。如果您有兴趣,请查看附录1 。
2个步骤:第一步将检查&#39; - &#39;是在正确的地方,而第二个将检查是否有4个连续相等的数字。
我将从第二步开始,这是最耗费内存的一步:正则表达式,检查是否没有连续的4个数字。以下正则表达式将执行:
((\d)(?!\2{3})){16}
说明:
( # group 1 start
(\d) # group 2: match a digit
(?!\2{3}) # negative lookahead: not 3 times group 2
){16} # repeat that 16 times.
第一步是匹配4位数的组,最后用&#39; - &#39; (查看example 2)这里要解决的问题是确保如果第一和第二组数字由&#39; - &#39;分隔,那么所有组都需要用&分隔#39; - &#39 ;.我们设法通过在下一个正则表达式中使用对第2组的反向引用来实现这一点。
(\d{4})(-?)(\d{4})(\2\d{4}){2}
说明:
(\d{4}) # starting 4 digits
(-?) # group 2 contains a '-' or not
(\d{4}) # 2nd group of 4 digits
(\2\d{4}){2} # last 2 groups, starting with a backreference
# to group 2 ( a '-' or not)
示例程序:
import re
pattern1 = r"(\d{4})(-?)(\d{4})(\2\d{4}){2}"
pattern2 = r"((\d)(?!\2{3})){16}"
tests = ["5123-4567-8912-3456"]
for elt in tests:
if re.match( pattern1, elt):
print "example has dashes in correct place"
elt = elt.replace("-", "")
if re.match(pattern2, elt):
print "...and has the right numbers."
<强>附录:强> 现在是沙漠。我把一个正则表达式放在一起,一气呵成。让我们考虑每个数字所需的内容,具体取决于它在一个组中的位置:
因此,对于我们在示例1中使用的前瞻,我们需要为每个数字提供后续的所有可能性。让我们看看一组4位数的模式:
(
(\d) # the digit at hand
(?! # negative lookahead
\2{3} # digit, digit, digit
|\2{2}-\2 # OR digit, digit, dash, digit
|\2-\2{2} # OR digit, dash, digit, digit
|-\2{3} # OR dash, digit, digit, digit
)
){4} # 4 times, for each digit in a group of 4
我们希望将其扩展为16位数。我们需要定义是否可以添加&#39; - &#39;在数字之前。一个简单的-?
不会做,因为信用卡并不是以破折号开头的。让我们使用交替:
(? # if
(?<=\d{4}) # lookbehind: there are 4 preceding digits
-? # then: '-' or not
| # else: nothing
)
结合起来,这将我们带到:
\b((?(?<=\d{4})-?|)(\d)(?!\2{3}|\2{2}-\2|\2-\2{2}|-\2{3})){16}\b
看看example 3。我们需要双方都使用\ b,因为我们希望确保在匹配成功时匹配complete
字符串。
让我们公平:如果这是可行的方法,我们会怀疑。从好的方面来说,我们现在有一个合理的理由分两步:python的标准版本不支持条件,什么不支持。您可以使用替换来解决此问题。或者切换编程语言。 ; - )
附录2:人们问我16
来自example 3的位置。完整的字符串长度是19个字符是不是真的?原因是只要内部正则表达式(组1)匹配一次,它就与[0-9]
或-[0-9]
匹配。这场比赛必须成功完成16次。
答案 1 :(得分:1)
你的正则表达式几乎是正确的。它要求四个短划线终止的数字组。你想要的是三个以字符串结尾的组,然后是一个非破折号终止的组,或一个没有破折号的blob:
(?:[0-9]{4}-){3}[0-9]{4}|[0-9]{16}
[Link]
由于您不需要捕获内容,因此我创建了组non-capturing。您也可以使用\d
代替[0-9]
:
(?:\d{4}-?){3}\d{4}
[Link]
连续数字的验证可能更容易在单独的步骤中完成。一旦正则表达式匹配通过,删除所有破折号:
num = num.replace('-', '')
现在使用itertools.groupby检查重复的数字,例如question / answer:
from itertools import groupby
if max(len(list(g)) for _, g in groupby(num)) >= 4:
print('Invalid: too many repeated digits')
完整代码
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')
答案 2 :(得分:1)
除非你真的想要/需要使用 regex ,否则这个任务可以通过这样简单的python代码来解决:
import itertools
card = "5133-3467-8912-.456"
# Check if hyphens are ok
if (len(card.split('-')) == 1 and len(card) == 16) or (len(card.split('-')) == 4 and all(len(i) == 4 for i in card.split("-"))):
# Remove all hyphens (if any)
card = card.replace("-", "")
try:
# Check if numbers only
int(card)
# Check if more than 3 repeated digits
if max(len(list(g)) for _, g in itertools.groupby(card)) > 3:
print("Failed: 4+ repeated digits")
else:
print("Passed")
except ValueError as e:
print("Failed: non-digit characters")
else:
print("Failed: bad hyphens or length")
答案 3 :(得分:0)
问题陈述:
正则表达式:
^(4|5|6)[1-9]{3}-?[1-9]{4}-?[1-9]{4}-?[1-9]{4}$
正则表达式:
[a-zA-z]
正则表达式:
(\d)\1{3,}
完整代码:
import re
new_cc=str(input())
#### to check the total lengt
without_hyp=new_cc.replace("-","")
###check for starting with 4,5 or 6 and {1234}: 4 digits within each group
match=re.search(r"^(4|5|6)[1-9]{3}-?[1-9]{4}-?[1-9]{4}-?[1-9]{4}$",str(new_cc))
### check for alphabet characters
nomatch=re.search(r"[a-zA-z]",str(new_cc))
##check for repetative numbers
con=re.search(r"(\d)\1{3,}",str(without_hyp))
if nomatch == None:
if match != None:
if len(new_cc.replace("-","")) == 16:
if match.group(0):
if con == None:
print('Valid')
else:
print('Invalid')
else:
print('Invalid')
else:
print('Invalid')
else:
print('Invalid')
else:
print('Invalid')