【问题标题】:Regex without positive lookahead to match password with one uppercase, one lowercase, one digit and at least eight characters正则表达式没有正向前瞻来匹配一个大写、一个小写、一个数字和至少八个字符的密码
【发布时间】:2014-11-14 05:16:20
【问题描述】:

我正在寻找一个匹配至少 8 个字符、至少一个大写字符、至少一个小写字符和至少一个数字的字符串(即密码)的正则表达式。

一个有效的正则表达式(在here 的帮助下)是:

(^(?=.*\d)(?=.*[a-z])(?=.*[A-Z])[0-9a-zA-Z]{8,}$)

此正则表达式使用正向前瞻 (?=)。这是一项昂贵的操作。是否可以在不使用积极前瞻的情况下制作这个正则表达式?

【问题讨论】:

  • 这是一项昂贵的操作 你为什么这么说?您始终可以接受来自用户的^[0-9a-zA-Z]{8,}$ 并使用代码进行验证。
  • 反正使用正则表达式的范围很广。我不知道这是谁开始的。这项工作不适合正则表达式。使用代码对其进行测试而不是依赖正则表达式引擎并希望它做得最好,这样会更快、更准确。
  • @anubhava 一切都保存在缓冲区中的事实。有人通过Mastering Regular Expression Third Edition 书解释了这一点。当然,这在代码中更快,但这不是问题。是否可以使用没有前瞻的正则表达式来做到这一点?
  • 我们不应该以这样的理由尝试解决问题。为什么创建一些微小的缓冲区会给您带来任何问题?你的内存不足了吗?即使使用正则表达式本身也会产生一些小成本,所以为什么还要使用正则表达式。
  • @Mariano 确实不正常。像这样广泛使用 pcre 几乎是作弊,因为它依赖的东西超出了对正则表达式的公认理解能力。但无论如何,不​​错的 hack。

标签: regex


【解决方案1】:

至少 8 个字符,至少 1 个大写字符, 至少一个小写字符和至少一个数字

有点像拼图

好的,我将把它当作一个谜题,前提是:

  • 不使用正则表达式的编码会更有效。
  • 与单独使用正则表达式的成本相比,前瞻并不昂贵。

而且这种解决方案可能比使用前瞻更昂贵。

说明

  1. 我们可以使用类似的子模式

    \A(?:[A-Z]|[a-z]|[0-9]|.){8,}
    

    检查主题中至少有 8 个字符,同时提供 4 个选项(大写、小写、数字或其他字符)。

  2. 然后,我们将为前 3 个必需选项创建一个反向引用:

    \A(?:(?<upper>[A-Z])|(?<lower>[a-z])|(?<digit>[0-9])|.){8,}
    
  3. 最后,我们将使用 IF 子句来检查每个组是否被捕获:

    (?(upper)  (?#check 2nd condition)  |  (?#make it fail)  )
    

    如果不满足任何条件,使用(?!) 使其失败:

    (?(upper)(?(lower)(?(digit)|(?!))|(?!))|(?!))
    

正则表达式

\A                        #beggining of string
(?>                       #MAIN iteration (atomic only for efficiency)
    (?<upper>[A-Z])       #  an uppercase letter
  |                       # or
    (?<lower>[a-z])       #  a lowercase letter
  |                       # or
    (?<digit>[0-9])       #  a digit
  |                       # or
    .                     #  anything else
){8,}?                    #REPEATED 8+ times
                          #
                          #CONDITIONS:
(?(upper)                 # 1. There must be at least 1 uppercase
    (?(lower)             #    2. If (1), there must be 1 lowercase
        (?(digit)         #       3. If (2), there must be 1 digit
          | (?!)          #          Else fail
        )                 #
      | (?!)              #       Else fail
    )                     #
  | (?!)                  #    Else fail
)                         #

单线:

\A(?>(?<upper>[A-Z])|(?<lower>[a-z])|(?<digit>[0-9])|.){8,}?(?(upper)(?(lower)(?(digit)|(?!))|(?!))|(?!))

regex101 demo

【讨论】:

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