我正在尝试在 PHP 中编写一个验证以下内容的正则表达式:
- 至少 10 个字符
- 至少有 2 个大写字符
- 至少有 2 个数字或符号
我几乎查看了我能找到的所有参考资料,但无济于事。
我想我可以单独测试,但这让我很伤心:(
有人可以帮忙吗?(然后把我送到一个我可以用简单的英语 Reg Ex 学习的地方?)
我正在尝试在 PHP 中编写一个验证以下内容的正则表达式:
我几乎查看了我能找到的所有参考资料,但无济于事。
我想我可以单独测试,但这让我很伤心:(
有人可以帮忙吗?(然后把我送到一个我可以用简单的英语 Reg Ex 学习的地方?)
(这是很多熵)
(图片来自 XKCD)
考虑到这一点,如果密码长度高于 X(例如.. 20),您可能需要考虑删除规则 2 和 3,或者将最小值增加到至少 16 个字符(作为唯一规则)。
至于你的要求:
与拥有一个庞大、丑陋、难以维护的高级正则表达式相反,您可能希望将问题分解为较小的部分,并使用专用函数分别处理每一位。
为此,您可以查看ctype_*
函数、count_chars()和多字节字符串函数。
现在丑了:
此高级 RegEx 将返回true
或false
根据您的规则:
preg_match('/^(?=.{10,}$)(?=.*?[A-Z].*?[A-Z])(?=.*?([\x20-\x40\x5b-\x60\x7b-\x7e\x80-\xbf]).*?(?1).*?$).*$/',$string);
在这里测试演示:http ://regex101.com/r/qE9eB2
第一部分(LookAhead):(?=.{10,}$)
将检查字符串长度,如果它至少有 10 个字符,则继续。您可以放弃它并使用strlen()甚至更好的 mb_strlen()进行检查。
第二部分(也是 LookAhead):(?=.*?[A-Z].*?[A-Z])
将检查是否存在 2 个大写字符。您也可以$upper=preg_replace('/[^A-Z]/','',$string)
改为 a 并将字符数计为$upper
两个以上。
3rd LookAhead 使用一个字符类:[\x20-\x40\x5b-\x60\x7b-\x7e\x80-\xbf]
为常见符号使用十六进制转义字符范围(几乎可以在普通键盘上找到所有符号)。您也可以$sym=preg_replace('/[^a-zA-Z]/','',$string)
改为 a 并将字符数计为$sym
两个以上。注意:为了缩短我使用递归组(?1)
不再重复相同的字符类
对于学习,我所知道的最全面的 RegExp 参考是:regular-expressions.info
您可以使用前瞻来确保正确包含您要查找的内容。
/(?=.*[A-Z].*[A-Z])(?=.*[^a-zA-Z].*[^a-zA-Z]).{10,}/
我一直喜欢用好的旧程序代码来处理这样的事情。正则表达式可能很有用,但它们也可能有点麻烦,特别是对于代码维护和快速扫描(正则表达式并不完全是可读性的例子)。
function strContains($string, $contains, $n = 1, $exact = false) {
$length = strlen($string);
$tally = 0;
for ($i = 0; $i < $length; $i++) {
if (strpos($contains, $string[$i]) !== false) {
$tally++;
}
}
return ($exact ? $tally == $n : $tally >= $n);
}
function validPassword($password) {
if (strlen($password) < 10) {
return false;
}
$upperChars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
$upperCount = 2;
if (strContains($password, $upperChars, $upperCount) === false) {
return false;
}
$numSymChars = '0123456789!"#$%&\'()*+,-./:;<=>?@[\\]^_`{|}~';
$numSymCount = 2;
if (strContains($password, $numSymChars, $numSymCount) === false) {
return false;
}
return true;
}