我想要一个密码字符串的正则表达式,其中至少包含以下四种字符中的三种:
至少应包含8个字符。
答案 0 :(得分:10)
鉴于这些要求可能产生的怪物 a ,我怀疑你实际上会更好地做这个多次检查,比如(伪-code):
def check_password (s):
if len(s) < 8:
return false
rules_followed = 0
if match (s, "[a-z]") rules_followed++;
if match (s, "[A-Z]") rules_followed++;
if match (s, "[0-9]") rules_followed++;
if match (s, "[!$#%]") rules_followed++; # et cetera
if rules_followed < 3:
return false
return true
当其他人必须维护您的代码时(或者即使您必须在六个月后维护它),这可能更具可读性。
现在我意识到这可能并不总是可能的(例如,您可能会遇到只允许一个正则表达式进行验证的框架)。
但是,如果 可能,我强烈建议你考虑一下。您应该始终尝试优化的第一个是可读性。
a 你要么最终得到其中一个大规模的前瞻性正则表达式,要么最终包含由|
分隔的十六种排序可能性。
这些都不像简单的代码段那样高效或可读。
答案 1 :(得分:3)
首先,这是paxdiablo代码的C#翻译:
public bool Validate(string input)
{
if (input == null || input.Length < 8)
return false;
int counter = 0;
if (input.Any(Char.IsLower)) counter++;
if (input.Any(Char.IsUpper)) counter++;
if (input.Any(Char.IsDigit)) counter++;
if (input.Any(c => Char.IsPunctuation(c) || Char.IsSymbol(c))) counter++;
return counter >= 3;
}
如果您坚持使用正则表达式,则可以使用与Fun With .NET Regex Balancing Groups上类似的模式:
^
(?=.*[a-z](?<Counter>))?
(?=.*[A-Z](?<Counter>))?
(?=.*[0-9](?<Counter>))?
(?=.*[^a-zA-Z0-9](?<Counter>))?
(?<-Counter>){3} # check we've had at least 3 groups
.{8}
您也可以允许Unicode classes:
^
(?=.*\p{Ll}(?<Counter>))?
(?=.*\p{Lu}(?<Counter>))?
(?=.*\p{Nd}(?<Counter>))?
(?=.*[\p{S}\p{P}](?<Counter>))?
(?<-Counter>){3}
.{8}
答案 2 :(得分:2)
扩展了正则表达式的PCRE版本:
/^(?:
(?=.*[a-z]) # look ahead: at least one from a-z
(?=.*[A-Z]) # look ahead: at least one from A-Z
(?=.*[0-9]) # look ahead: at least one from 0-9
| # or...
(?=.*[a-z]) # look ahead: at least one from a-z
(?=.*[A-Z]) # look ahead: at least one from A-Z
(?=.*[^a-zA-Z0-9]) # look ahead: at least one from special chars
| # or...
(?=.*[a-z]) # look ahead: at least one from a-z
(?=.*[0-9]) # look ahead: at least one from 0-9
(?=.*[^a-zA-Z0-9]) # look ahead: at least one from special chars
| # or...
(?=.*[A-Z]) # look ahead: at least one from A-Z
(?=.*[0-9]) # look ahead: at least one from 0-9
(?=.*[^a-zA-Z0-9]) # look ahead: at least one from special chars
)
\S{8,} # at least 8 non-spaces
$/x
答案 3 :(得分:1)
组合学并不是那么糟糕 - 只有四种方法可以选择四种可能性中的三种;您可以在正则表达式的开头测试具有前瞻性的那些,然后检查实际匹配的八个字符:
^(?:(?=.*[A-Z])(?=.*[a-z])(?=.*\d)|(?=.*[A-Z])(?=.*[a-z])(?=.*[_\W])|(?=.*[A-Z])(?=.*\d)(?=.*[_\W])|(?=.*[a-z])(?=.*\d)(?=.*[_\W])).{8}
(锚定是为了在失败时提高效率,没有它就会有效。)
密码可能无关紧要,但上述版本可能会对同一类型的字符多次查看整个字符串,尤其是失败时。您可能会以这样的方式考虑它,但代价是可读性:
^(?:(?=.*[A-Z])(?:(?=.*[a-z])(?:(?=.*\d)|(?=.*[_\W]))|(?=.*\d)(?=.*[_\W]))|(?=.*[a-z])(?=.*\d)(?=.*[_\W])).{8}
答案 4 :(得分:0)
正确回答我的问题:
正则表达式:
^((= [\ d])(= [AZ])(= [AZ])|??????(= [AZ])(= [AZ])(= [^ \ W \ d \ S])|(= [\ d])(= [AZ])(= [^ \ W \ d \ S])|????(= [\ d])(?=。[AZ])(?=。[^ \ W \ d \ S]))。{8,30} $
感谢。