【问题标题】:Python Regex: password must contain at least one uppercase letter and numberPython Regex:密码必须至少包含一个大写字母和数字
【发布时间】:2016-02-08 21:04:17
【问题描述】:

我正在使用 Python 和 Flask 对密码进行表单验证。密码必须包含至少一个大写字母和至少一个数字

我目前失败的尝试...

re.compile(r'^[A-Z\d]$')

【问题讨论】:

  • '\d.*[A-Z]|[A-Z].*\d'
  • @PierreLafortune 你介意解释一下你的正则表达式吗?我认为它有效......
  • @PierreLafortune 其实不行。
  • 它有效。我刚刚测试了 20 个不同的字符串。
  • 您可以对密码施加的最重要要求是最小长度。

标签: python regex flask


【解决方案1】:

我们可以使用'\d.*[A-Z]|[A-Z].*\d' 模式来搜索至少有一个大写字母和一个数字的条目。从逻辑上讲,大写字母和数字在字符串中出现的方式只有两种。要么字母在前,数字在后,要么数字在前,字母在后。

管道 |表示“或”,因此我们将分别查看每一侧。 \d.*[A-Z] 匹配后跟大写字母的数字,[A-Z].*\d 匹配后跟数字的任何大写字母。

words = ['Password1', 'password2', 'passwordthree', 'P4', 'mypassworD1!!!', '898*(*^$^@%&#abcdef']
for x in words:
    print re.search('\d.*[A-Z]|[A-Z].*\d', x)
#<_sre.SRE_Match object at 0x00000000088146B0>
#None
#None
#<_sre.SRE_Match object at 0x00000000088146B0>
#<_sre.SRE_Match object at 0x00000000088146B0>
#None

【讨论】:

  • 如果有两个以上的条件怎么办?例如,密码必须至少包含一个大写字母、一个小写字母、一个数字和以下特殊字符之一:`!@_$%'。这产生了 24 种可能的排序。虽然您的方法适用于两种情况,但它并不是解决一般问题的最佳方法。
【解决方案2】:

另一种选择是使用lookahead

^(?=.*?[A-Z]).*\d

demo at regex101

^ 的前瞻开始检查 [A-Z] 是否在前面。如果匹配一个数字。

【讨论】:

    【解决方案3】:

    要匹配至少包含一位数字字符的字符串,请使用:

    .*[0-9].*
    

    类似的正则表达式适用于检查大小写。

    【讨论】:

      【解决方案4】:

      正则表达式没有 AND 运算符,因此当有效性由某事 AND 某事和某事定义时,很难编写匹配有效密码的 正规表达式。

      但是,正则表达式确实有 OR 运算符,所以只需应用 DeMorgan 定理,并编写一个匹配无效密码的正则表达式:

      任何没有数字或任何没有大写的东西

      所以:

      ^([^0-9]*|[^A-Z]*)$
      

      如果有任何匹配,那么它是一个无效的密码。

      【讨论】:

      • 星号将匹配 0 个或多个字符...因此删除它..这也可以像 [^0-9A-Z]
      • @repzero,不,这是不正确的。我的正则表达式匹配“1”和“A”。你的没有
      • 请注意,它是用于匹配一个字符串,而不是搜索字符串,如果这对你的想法有影响的话
      • 还是要争辩,但我放了锚点来表明你应该匹配整个字符串
      • RE 是正确的。也许你应该强调这个 RE 是为了匹配无效密码 - 你是不公平的 dv 因为那可能不清楚。
      【解决方案5】:

      我认为这对你有用:

      ^(?=.*[A-Z])(?=.*\d).*$
      

      【讨论】:

      • 发布了很多答案,“我认为”你买不起。不管它是否有效。如果不是..不要发布,因为答案应该大大增加一些东西,以便我们可以从中学习。审查结束。
      【解决方案6】:

      使用两个非贪婪的前瞻断言:

      ^(?=[^A-Z]*[A-Z])(?=[^0-9]*[0-9])
      

      上面断言当前输入位置(字符串的开头),由 0 个或多个非大写字母后跟一个大写字母组成,它还由 0 个或多个非数字后跟一个数字组成。

      import re
      
      tests = [
          'x1bcAd',
          'xAbcd1d',
          'abcde',
          '1234',
          'AAAA'
      ]
      
      for test in tests:
          m = re.match(r'^(?=[^A-Z]*[A-Z])(?=[^0-9]*[0-9])', test)
          print(test, 'Passed' if m else 'Failed')
      

      打印:

      x1bcAd Passed
      xAbcd1d Passed
      abcde Failed
      1234 Failed
      AAAA Failed
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-04-21
        • 2021-09-08
        相关资源
        最近更新 更多