首页 > 解决方案 > 蟒蛇 | 正则表达式 | 字符串验证

问题描述

import re
u,d,c=0,0,0
n=int(input())
for i in range(0,n):
    uid=str(input())
    uid = "".join(sorted(uid))
    if (len(uid)<=10):   
        for i in uid:
            if(re.search("[a-z]", uid)):
                flag=-1
            if(re.search("[0-9]", uid)):
                flag=-1
            if(re.search("[A-Z]", uid)):
                flag=-1
            if(uid.count(i)>1):
                c+=1
            if(i.isupper()):  #uppercase
                u+=1
            if(i.isdigit()):   
                    d+=1    
    if(u>=2 and d>=3 and flag==-1 and c==0):
        print("Valid")
    else:
        print("Invalid")

上面的代码用于验证uid(string).
当我传递 2 个值并且第一个值无效时,它会被正确验证并打印"invalid"然后打印下一个值,即使它是有效的,它仍然会打印"invalid". 然而,如果第一个值有效,则打印"valid",如果下一个值无效,则打印"invalid"
添加图片供参考(图片中第一个值因重复字符而无效,但第二个值有效,仍然显示无效)

在此处输入图像描述

验证 uid 的规则:

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

标签: pythonregex

解决方案


您通过尝试将字符串与以下正则表达式匹配来执行验证。

^(?=(?:.*\d){3})(?=(?:.*[A-Z]){2})(?!.*(.).*\1)[A-Za-z0-9]{10}$

启动你的引擎!

Python 的正则表达式引擎执行以下操作。

^               : assert beginning of string
(?=             : positive lookahead to assert string contains at
                  least three digits
  (?:.*\d)      : match 0+ chars, then 1 digit in a non-capture group
  {3}           : execute non-capture group thrice
)               : end positive-lookahead
(?=             : positive lookahead to assert string contains at
                  least two capital letters
  (?:.*[A-Z])   : match 0+ chars, then 1 uppercase letter in a
                  non-capture group
  {2}           : execute non-capture group twice 
)               : end positive-lookahead
(?!             : negative lookahead to assert string does contain 
                  the same character twice
  .*(.).*\1     : match 0+ chars, 1 character saved to capture group
                  1, 0+ chars, contents of capture group 1
)               : end negative lookahead
[A-Za-z0-9]{10} : match 10 letters or digits
$               : assert end of string

请注意,肯定的前瞻用于断言字符串包含“某物”(这里,至少 3 个数字和至少 2 个大写字母)。否定前瞻用于断言字符串不包含“某物”(此处为重复的字符)。[A-Za-z0-9]{10}^$锚点一起断言字符串中允许的字符和字符串的长度。

@Thefourthbird 在评论中建议了此正则表达式的更有效变体:

^(?=(?:[^\d\s]*\d){3})(?=(?:[^A-Z\s]*[A-Z]){2})(?!.*?(.).*\1)[A-Za-z0-9]{10}$

如所见,该正则表达式需要 596 个步骤用于测试字符串。这与我提出的正则表达式所需的 906 相比。


推荐阅读