【问题标题】:How can I require that at least two lookahead patterns match within one regex?如何要求在一个正则表达式中至少匹配两个前瞻模式?
【发布时间】:2014-12-02 03:34:06
【问题描述】:

以下正则表达式确保密码至少包含一个小写字母、一个大写字母、一个数字和一个特殊字符:

^(?=.*[A-Z])(?=.*[a-z])(?=.*[0-9])(?=.*[^a-zA-Z0-9\s]).*$

这行得通。在此基础上,我想要求仅满足其中两个组才能使密码有效。

例如,这些是有效密码:aaaaa5、BFEWREWRE77、#2ccc。

我可以修改这个正则表达式来支持这个要求吗?

【问题讨论】:

  • 这不是正则表达式的工作。最好尝试遍历字符串并计算它包含的每种字符的数量。接下来根据您的规则检查计数。下一个阅读代码的人也更清楚。
  • 当然,它可能更适合代码。但我想用正则表达式来做。怎么办?

标签: regex lookahead


【解决方案1】:

你可以这样做:

禁止使用空格:

^(?=([A-Z]+|[a-z]+|[0-9]+|[^a-zA-Z0-9\s]+))\1\S+$

允许有空格:

^\s*(?=((?:[A-Z]+\s*)+|(?:[a-z]+\s*)+|(?:[0-9]+\s*)+|(?:[^a-zA-Z0-9\s]+\s*)+))\1.+$

解释:

(?=([A-Z]+|[a-z]+|[0-9]+|[^a-zA-Z0-9\s]+))\1 模拟atomic group (?>[A-Z]+|[a-z]+|[0-9]+|[^a-zA-Z0-9\s]+)。因此,一旦匹配了该组的一个分支,正则表达式引擎就不再允许在匹配的字符内回溯。

由于量词默认是贪婪的,因此其中一个类别的所有字符都由原子组匹配。

\S. 匹配的下一个字符显然与组中使用的字符类别不同。

注意:对于第二种模式,由于字符串中使用的字符没有限制,所以你不需要测试字符串直到最后,所以你可以这样写:

^\s*(?=((?:[A-Z]+\s*)+|(?:[a-z]+\s*)+|(?:[0-9]+\s*)+|(?:[^a-zA-Z0-9\s]+\s*)+))\1.

【讨论】:

  • 非常聪明,脱帽+1
  • 叮叮叮叮!我们有一个赢家。它又好又短。知道可以做到。非常感谢!
  • @ChadJohnson:允许空格吗?
  • 不——谢谢你的提问。嘿,再问一个问题:如果你想要求的不仅仅是两个而是三个字符,你将如何强制执行三个?
  • @ChadJohnson:对三个字符类做同样的事情(遵循相同的想法),你会得到这个:regex101.com/r/pK9xM4/1 它相对有效但有点长。在这种情况下,简单的方法是用四种不同的模式测试每个字符类并计算成功的次数。
【解决方案2】:

既然你要求这个长的正则表达式:

^(?:(?=.*[A-Z])(?=.*[a-z])|(?=.*[A-Z])(?=.*[0-9])|(?=.*[A-Z])(?=.*[^a-zA-Z0-9\s])|(?=.*[a-z])(?=.*[0-9])|(?=.*[a-z])(?=.*[^a-zA-Z0-9\s])|(?=.*[0-9])(?=.*[^a-zA-Z0-9\s])).+$

RegEx Demo

【讨论】:

  • 哈哈...不错。这当然有效,尽管我认为我会选择 Casimir et Hippolyte 的版本,因为它更短:)
【解决方案3】:

大多数现代引擎都提供条件。
这是一个简单的示例模式,它禁止重新进入同一组
并保证 Y 中的 X 要求。

本质上,组的匹配没有特定的顺序
量词编号X,它是导致对齐的标准。

它的可扩展性很强,只需在交替中添加一个新组即可。
X 设置为要匹配的唯一组数。

这个设置为 4 个中的 3 个。
只需满足您的任何边界要求即可完成它,例如
^+regex_below+.*$

此外,它会随时间消耗。如果在那里,它可能很容易在前瞻内
可以是任何长度或其他特定属性。

请注意,如果引擎不支持条件语句(并非全部支持),那么这将不起作用。

 #  (?:.*?(?>((?(1)(?!))[a-z]+)|((?(2)(?!))[A-Z]+)|((?(3)(?!))[0-9]+)|((?(4)(?!))[^a-zA-Z0-9\s]+))){3}

 (?:
      .*?     
      (?>
           (                        # (1)
                (?(1) (?!) )
                [a-z]+ 
           )
        |  (                        # (2)
                (?(2) (?!) )
                [A-Z]+ 
           )
        |  (                        # (3)
                (?(3) (?!) )
                [0-9]+ 
           )
        |  (                        # (4)
                (?(4) (?!) )
                [^a-zA-Z0-9\s]+ 
           )
      )
 ){3}

X 为 4(共 4 个)时的样本输出

 **  Grp 0 -  ( pos 0 , len 11 ) 
B,B_+&*%#a0  
 **  Grp 1 -  ( pos 9 , len 1 ) 
a  
 **  Grp 2 -  ( pos 0 , len 1 ) 
B  
 **  Grp 3 -  ( pos 10 , len 1 ) 
0  
 **  Grp 4 -  ( pos 1 , len 1 ) 
,  

【讨论】:

  • 我觉得我的脑袋爆炸了。
  • @ChadJohnson - 希望爆炸不是致命的。我留下了这个正则表达式以供高级使用。它并不是真的要被任何人理解——也许是少数人。
  • 哈哈,开个玩笑。这是好东西...感谢分享:)
  • @ChadJohnson - 对此构造进行了大量调试测试。发现在交替周围添加原子组修复了一堆延迟回溯。并且,发现性能方面与锚点位置的大量前瞻一样快(即^)。这意味着两个范式合二为一。小于或等于。虽然取决于条件。这个特殊的条件可以在 Dot-Net fwiw 中模拟。新年快乐!!
【解决方案4】:

你必须做类似的事情:

^(
    (?=1)(?=2)
    |
    (?=1)(?=3)
    |
    (?=1)(?=4)
    |
    (?=2)(?=3)
    |
    (?=2)(?=4)
    |
    (?=3)(?=4)
).*$

其中 1、2、3 和 4 是您的不同模式

【讨论】:

    猜你喜欢
    • 2017-10-01
    • 1970-01-01
    • 2013-07-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-12-08
    • 2012-04-08
    • 1970-01-01
    相关资源
    最近更新 更多