我是RegEx的新手,已经做了很多搜索,但没有找到具体的内容。
我正在编写一个验证密码字符串的正则表达式。 可接受的字符串必须至少有4种字符类型中的3种:数字,小写,大写,特殊字符[< + $ *]],但不得包含另一组特殊字符(|; {})。
我了解了包含(即如果它是正确的方法)。
看起来像这样:
^((a-z | A-Z |\d)(a-z|A-Z|[<+$*])(a-z|[<+$*]|\d)(A-Z|[<+$*]|\d)).*$
如何确保用户不输入特殊字符(|; {}) 这是我尝试使用排除字符串:
^(?:(?![|;{}]).)*$
我尝试了一些技巧,将两者合并在一个regEx中,但无法让它工作。
关于如何做到这一点的任何输入?
答案 0 :(得分:9)
不要试图在一个正则表达式中完成所有操作。进行两次不同的检查。
假设你在Perl工作(因为你没有指定语言):
$valid_pw =
( $pw =~ /^((a-z | A-Z |\d)(a-z|A-Z|[<+$*])(a-z|[<+$*]|\d)(A-Z|[<+$*]|\d)).*$/ ) &&
( $pw !~ /\|;{}/ );
您说“如果PW符合所有包含规则,并且PW与任何排除的字符都不匹配,则密码有效。”
看看有多清楚比@Jerry的回应更清楚:
^(?![^a-zA-Z]*$|[^a-z0-9]*$|[^a-z<+$*]*$|[^A-Z0-9]*$|[^A-Z<+$*]*$|[^0-9<+$*]*$|.*[|;{}]).*$
我不怀疑Jerry的版本是否有效,但你想保留哪一个?
事实上,你可以进一步分解它并且非常清楚:
my $cases_matched = 0;
$cases_matched++ if ( $pw =~ /\d/ ); # digits
$cases_matched++ if ( $pw =~ /[a-z]/ ); # lowercase
$cases_matched++ if ( $pw =~ /[A-Z]/ ); # uppercase
$cases_matched++ if ( $pw =~ /<\+\$\*/ ); # special characters
my $is_valid = ($cases_matched >= 3) && ($pw !~ /\|;{}/); # At least 3, and none forbidden.
当然,这需要6行而不是1行,但是在你回去并且必须添加新规则或者弄清楚代码的作用的一年中,你会很高兴你这样写。< / p>
仅仅因为你可以在一个正则表达式中执行它并不意味着你应该。
答案 1 :(得分:2)
您当前的正则表达式不适用于强制实施4个要求中的至少3个。使用正则表达式变得相当复杂,但在我看来,最好的方法是使用包含所有失败案例的负向前瞻,这样如果满足任何负面情况,整个匹配将失败。在这种情况下,“至少3个4”的要求也可以描述为“如果找不到任何2个组则失败”。这也使得添加最终要求变得非常容易,以确保找不到[|;{}]
中的字符:
^ # beginning of string anchor
(?! # fail if
[^a-zA-Z]*$ # no [a-z] or [A-Z] anywhere
| # OR
[^a-z0-9]*$ # no [a-z] or [0-9] anywhere
| # OR
[^a-z<+$*]*$ # no [a-z] or [<+$*] anywhere
| # OR
[^A-Z0-9]*$ # no [A-Z] or [0-9] anywhere
| # OR
[^A-Z<+$*]*$ # no [A-Z] or [<+$*] anywhere
| # OR
[^0-9<+$*]*$ # no [0-9] or [<+$*] anywhere
| # OR
.*[|;{}] # a character from [|;{}] exists
)
.*$ # made it past the negative cases, match the entire string
这是一行:
^(?![^a-zA-Z]*$|[^a-z0-9]*$|[^a-z<+$*]*$|[^A-Z0-9]*$|[^A-Z<+$*]*$|[^0-9<+$*]*$|.*[|;{}]).*$
答案 2 :(得分:1)
这只是为了接受你提到的字符:
^(?:(?=.*[0-9])(?=.*[a-z])(?=.*[<+$*)])|(?=.*[a-z])(?=.*[<+$*)])(?=.*[A-Z])|(?=.*[0-9])(?=.*[A-Z])(?=.*[<+$*)])|(?=.*[0-9])(?=.*[a-z])(?=.*[A-Z]))[0-9A-Za-z<+$*)]+$
对于您提及的所有字符,以及除<{1}}之外的任何特殊字符。
|;{}
(一个不同之处在于第一个正则表达式不接受特殊字符^(?:(?=.*[0-9])(?=.*[a-z])(?=.*[<+$*)])|(?=.*[a-z])(?=.*[<+$*)])(?=.*[A-Z])|(?=.*[0-9])(?=.*[A-Z])(?=.*[<+$*)])|(?=.*[0-9])(?=.*[a-z])(?=.*[A-Z]))(?!.*[|;{}].*$).+$
,但第二个正则表达式确实存在。)
我还使用了@
,因为密码在逻辑上不能是0宽度。
但是,它比F.J的正则表达式更长,更长,哦。那是因为我正在使用积极的前瞻,这需要更多的检查。
答案 3 :(得分:-1)
&#34;我还没有测试过这个。我唯一不确定的可能是最后的4个最后3个检查。这使用4个捕获作为标志。这可能与其他人(可能更快)略有不同。&#34;
编辑 - 经过测试并通过。 在我看来,捕获标志是非常有用的。在这种情况下,没有前瞻,因为在这里,只检查捕获状态。而且没有回溯。它只是从头到尾检查每个字符一次。这可能是最快的方式。
# ^(?:(?!\1)\d()|(?!\2)[a-z]()|(?!\3)[A-Z]()|(?!\4)[<+$*)]()|[^|;{}])+$(?:\1\2\3|\1\2\4|\1\3\4|\2\3\4)
^
(?:
(?! \1 )
\d
( ) # (1)
| (?! \2 )
[a-z]
( ) # (2)
| (?! \3 )
[A-Z]
( ) # (3)
| (?! \4 )
[<+$*)]
( ) # (4)
| [^|;{}]
)+
$
(?:
\1 \2 \3
| \1 \2 \4
| \1 \3 \4
| \2 \3 \4
)