【问题标题】:Regex Python pattern [duplicate]正则表达式 Python 模式 [重复]
【发布时间】:2016-11-16 14:30:35
【问题描述】:

我正在尝试编写一个程序,它使用正则表达式来确保它传递的密码字符串是强的。强密码被定义为至少有八个字符长、包含大写和小写字符并且至少有一个数字的密码。到目前为止,我有以下代码。我花了几个小时修改正则表达式,但是我不能让它通过。每次我进行更改时,似乎强密码都被标记为弱密码,或者弱密码为强密码。知道如何改进吗?

import re


pass2Regex = re.compile(r'''
    \d*
    [a-zA-Z]*
    \d*
    [a-zA-Z]*
    ''',re.VERBOSE)


text = raw_input("enter your password\n")
if len(text) >= 8:
    search = pass2Regex.findall(text)
    if text in search:
        print "%s is a strong password" % (text)
    else:
        print "%s is a weak password" % (text)
else:
    print "%s is a weak password" % (text)

例如,现在如果密码是“231242441”,即使没有字母,它也会被标记为强密码。此外,当我尝试使用 + 而不是 * 时,它只会接受以数字等开头的密码。

感谢您的帮助

【问题讨论】:

标签: python regex


【解决方案1】:

您可以使用所有 python,因此不要将自己限制在单个正则表达式中。为密码必须满足的每个条件编写一个正则表达式。 “包含大写”?琐碎的。 “小写”?也是微不足道的。 “至少一位数”?没问题。 “至少 8 个字符长”?你甚至不需要正则表达式。

您可以级联测试,将一系列测试与and 组合在一起,或者将测试放在一个列表中并一次性应用它们,如下所示:

tests = [ "[A-Z]", "[a-z]", r"\d", ".{8}" ]
if all(re.search(pat, text) for pat in tests):
    print("It's a strong password")

为下一步节省您的时间。

【讨论】:

  • 如果他可以一次拥有所有东西,他为什么要这样做?
  • 因为任何单一的正则表达式“解决方案”,即使是你的,都远不如拆分它的可读性、可验证性或可扩展性(即可维护性)。
  • 我同意你的观点,大多数正则表达式解决方案都没有以详细模式编写 - 但是,如果你添加 cmets(这是我通常做的),我认为它们通常比查找每个函数的参数更直接 - 毕竟这是一个品味问题,我猜 :)
  • 详细模式很好,但您仍然有一个正则表达式,其中所有工作都在多个重叠的前瞻中完成,甚至不使用非贪婪通配符。谢谢,但我会通过的。而且 cmets 不是验证——它们可能是不正确的。
  • @Jan 我喜欢正则表达式。但是,能够编写/维护正则表达式的人比能够理解/更新/维护 Python 字符串方法的人少。如果有更简单、更清晰、更易于维护的方式,请选择它。
【解决方案2】:

正如其他人所提到的,这是lookarounds 的典型用例(在这种情况下为lookaheads)。
前瞻 在不消耗字符的情况下前瞻(这是一个断言)。
细分为您的需求:

强密码被定义为至少包含八个字符的密码 long,包含大写和小写字符,并且有 at 至少一位数。

^                    # anchors the expression to the beginning
    (?=[^a-z]*[a-z]) # not lowercase, followed by lowercase
    (?=[^A-Z]*[A-Z]) # not UPPERCASE, followed by UPPERCASE
    (?=\D*\d)        # not a digit, followed by a digit
    .{8,}            # at least 8 characters long
$                    # anchor the expression to the end

a demo on regex101.com


因此,对于您的代码 sn-p 这将是:
import re
pass2Regex = re.compile(r"""
    ^                    # anchors the expression to the beginning
        (?=[^a-z]*[a-z]) # not lowercase, followed by lowercase
        (?=[^A-Z]*[A-Z]) # not UPPERCASE, followed by UPPERCASE
        (?=\D*\d)        # not a digit, followed by a digit
        .{8,}            # at least 8 characters long
    $                    # anchor the expression to the end
""", re.VERBOSE)

password = "WeaK1234"
password2 = "strong?"

if pass2Regex.search(password):
    print "Strong!"

if pass2Regex.search(password2):
    print "Strong!"

【讨论】:

  • 我不太了解你们的 cmets 或主播的工作。你介意换句话解释一下吗?谢谢!
  • OP 代码实际上已经检查了字符串的长度,你不需要在末尾添加{8,}+ 就够了:)
  • @WiktorStribiżew:不知道,谢谢。
  • @brianhalperin: ^$ 确保分别匹配字符串的开头和结尾。
猜你喜欢
  • 2021-05-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-04-22
  • 2016-01-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多