正则表达式查找 4 个条件中的 3 个

Posted

技术标签:

【中文标题】正则表达式查找 4 个条件中的 3 个【英文标题】:Regex to find 3 out of 4 conditions 【发布时间】:2014-04-07 22:17:51 【问题描述】:

我的客户要求他们系统上的密码必须遵循一组特定的验证规则,但我很难想出一个“好的”正则表达式。

给我的规则是……

最少 8 个字符 允许任何字符 必须至少有一个实例来自以下四种字符类型中的三种...
    大写字符 小写字符 数字 “特殊字符”

当我按下更多时,“特殊字符”实际上就是其他所有内容(包括空格)。

我可以使用以下命令轻松检查所有四个实例中的至少一个...

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

以下工作,但它是可怕和混乱......

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

所以您不必自己解决,上面是检查(1,2,3|1,2,4|1,3,4|2,3,4),这是 4 个组的 4 种可能组合(其中数字与规则集中的“类型”相关)。

有没有“更好”、更清洁或更简单的方法来做到这一点?

(请注意,这将用于 ASP.NET 网站中的 <asp:RegularExpressionValidator> 控件,因此需要是 .NET 和 javascript 的有效正则表达式。)

【问题讨论】:

我不认为有一个“好的”单次模式可以做到这一点。最好的方法是将计数器变量设置为零并通过四个单独的测试将其递增。您可以使用正则表达式或内置函数(如果可用)执行这些测试(我不知道 asp) 我明白你在说什么@Casimiret,但这需要多个正则表达式和额外的自定义处理才能解决。不幸的是,这需要是一个单一的模式,因为它是一个“配置”,它将在网站的几个不同部分驱动 <asp:RegularExpressionValidator> 控件。 如果您有可能避免,对于这种类型的数据,RegularExpressionValidator 并找到其他方法来做到这一点,不要犹豫。请记住,简单的(?=.*[a-z]) 在性能方面很差,将其乘以 12... 最好的方法是使用<asp:CustomValidator>并编写自己的函数。 这应该是正确答案:***.com/a/5951154/1497565 【参考方案1】:

这并不是一个更好的解决方案,但是您可以将[^a-zA-Z0-9] 减少到[\W_],因为单词字符都是字母、数字和下划线字符。我认为在单个正则表达式中尝试执行此操作时无法避免交替。我认为您几乎有最好的解决方案。

一个轻微的优化是\d*[a-z]\w_*|\d*[A-Z]\w_* ~> \d*[a-zA-Z]\w_*,所以我可以删除其中一个交替集。如果你只允许 4 个中的 3 个,这是行不通的,但由于 \d*[A-Z][a-z]\w_* 被隐式允许,它可以工作。

(?=.8,)((?=.*\d)(?=.*[a-z])(?=.*[A-Z])|(?=.*\d)(?=.*[a-zA-Z])(?=.*[\W_])|(?=.*[a-z])(?=.*[A-Z])(?=.*[\W_])).*

扩展版:

(?=.8,)(
  (?=.*\d)(?=.*[a-z])(?=.*[A-Z])|
  (?=.*\d)(?=.*[a-zA-Z])(?=.*[\W_])|
  (?=.*[a-z])(?=.*[A-Z])(?=.*[\W_])
).*

由于 OP 指定的第四个条件,这个正则表达式甚至会匹配不可打印的字符,例如换行符。如果这是不可接受的,则修改包含 \W 的集合以允许更具体的特殊字符集。

【讨论】:

感谢@Daniel。我确实喜欢[\W_],尽管我个人认为它不像[^a-zA-Z0-9] 那样可读 我已经从上面的评论中删除了关于匹配“abcdefg1”的部分——我的正则表达式测试器默认i开关打开。关闭i,你的表达就完美了 有趣的想法...但是为什么它在我首选的检查器中不起作用? regextester.com @freefaller 我删除了这个想法,分组在前瞻中无法正常工作。但是我发现了一个 d'oh! 简化,它使正则表达式更容易理解。 @DanielGimenez 我必须保留一些特殊字符,所以请您帮帮我。我必须只保留 [@#$%^*()!&=\s] 这个。休息条件相同。【参考方案2】:

我想用这个改进公认的解决方案

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

【讨论】:

【参考方案3】:

除了 "AAAAAA1$"、"$$$$$$1a" 等字符串之外,上述正则表达式适用于大多数情况 这可能是仅在 ios(Objective C 和 Swift)中正则表达式“\d”存在问题的问题 以下修复在 iOS 中有效,即数字更改为 [0-9]

^((?=.*?[A-Z])(?=.*?[a-z])(?=.*?[0-9])|(?=.*?[A-Z])(?=.*?[a-z])(?=.*?[^a-zA-Z0-9])|(?=.*?[A-Z])(?=.*?[0-9])(?=.*?[^a-zA-Z0-9])|(?=.*?[a-z])(?=.*?[0-9])(?=.*?[^a-zA-Z0-9])).8,$

【讨论】:

【参考方案4】:

密码必须满足以下 4 条复杂性规则中的至少 3 条,

[至少 1 个大写字符 (A-Z) 至少 1 个小写字符 (a-z) 至少 1 个数字 (0-9) 至少 1 个特殊字符 — 不要忘记将空格也视为特殊字符]

至少 10 个字符

最多 128 个字符

一行中不超过 2 个相同的字符(例如,不允许 111 个)

'^(?!.(.)\12) ((?=.[a-z])(?=.[A-Z])(?=.[0-9])|(?=.[a-z])(?=.[A-Z])(?=.[^a-zA-Z0-9])|(?=.[A-Z])(?=.[0-9])(?=.[^a-zA-Z0-9])|(?=.[a-z])(?=.[0-9])(?=.*[^a-zA-Z0-9])).10,127$'

(?!.*(.)\12)

(?=.[a-z])(?=.[A-Z])(?=.*[0-9])

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

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

(?=.[a-z])(?=.[0-9])(?=.*[^a-zA-Z0-9])

.10,127

【讨论】:

以上是关于正则表达式查找 4 个条件中的 3 个的主要内容,如果未能解决你的问题,请参考以下文章

正则表达式查找字符串的最后一个字符[重复]

不用正则表达式来查找文本模式

用于检查 4 个不同字符组中的至少 3 个的正则表达式

正则表达式查找第 n 个逗号并删除逗号以及值

Python re模块与正则表达式详解

带有条件的java中的正则表达式