寻找另一个正则表达式的解释

时间:2011-11-26 01:41:12

标签: javascript regex

在我的正则表达式中,我试图匹配8到16个字符之间的密码,其中至少有2个符合以下条件:小写字母,大写字母和数字。

在我的表达中,我有:

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

但我不明白为什么它不会这样:

^((?=\d)(?=[a-z])(?=[A-Z])(?=\d)(?=[a-z])(?=[A-Z]){8,16})$

不“。*”只是意味着“零或更多的任何角色”?那么,如果我只是检查具体情况,为什么还需要呢?

为什么我需要在大括号定义密码限制之前的时间段?

还有一件事,我不明白“不消耗任何字符串”对“?=”的含义是什么意思。

4 个答案:

答案 0 :(得分:2)

您的最后两个问题是相关的。 ?=(顺便称之为前瞻)不会消耗任何字符串,这意味着它会测试字符串的条件但它本身是零字符长。如果前瞻为真,则匹配继续,但表达式的下一部分从检查前瞻之前的位置开始。

因为你的所有东西都是由前瞻组成的,所以它们的长度都是零。因此,要使{8,16}匹配某些内容,您需要先提供..{8,16}表示“8到16个字符,我不在乎这些字符是什么。” {8,16}之前没有任何内容的.{8,16}不是一个有效的表达式(或者至少不代表.*的意思)。

关于您的第一个问题,每个前瞻中都需要^,因为您的表达式以.*开头。这意味着“从字符串的最开头”开始,而不是“匹配字符串中的任何位置”。由于您不是仅尝试在字符串的开头匹配,^((?=.*\d.*\d)(?=.*[a-z].*[a-z])(?=.*[A-Z].*[A-Z]).{8,16})$ 允许您使前瞻符影响字符串中的任何位置。

最后,我担心你的正则表达式不起作用。因为前瞻是零长度的,所以将你所做的两次相同的前瞻两次匹配相同的东西。因此,此表达式仅检查您是否具有要强制执行的每种类型字符的单个实例,并且存在两个实例。你想要的表达式更像是这样:

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

那个表达式相当于更优雅:

{{1}}

(而且,在它到期的地方给予信任,丹尼斯打败了我最后的表达。干得好,先生。)

答案 1 :(得分:1)

问题是这个角色^意味着“正确的开始”。这意味着这些特定字符应该严格地位于您正在搜索的文本的开头,这不是您想要的。

答案 2 :(得分:1)

你的表达不会按你的意愿运作。

由于前瞻,(?=.*\d)的两个实例实际上都匹配相同的数字,因此只用一位数验证密码。

这应该有效:

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

答案 3 :(得分:1)

(?=.*\d)(?=\d)之间的区别在于,虽然它们都是零宽度前瞻,但如果字符串中的任何位置(在当前位置之后),前者将匹配,但后者仅在该数字紧跟在当前位置之后才匹配。因此,第一个正则表达式查找8-16个字符,包括一个数字,小写和大写。第二个正则表达式要求第一个字符是数字,小写和大写,这是荒谬的。如果您想要计算两位数,而不是(?=.*\d)(?=.*\d),请执行(?=.*\d.*\d)