我正在尝试用PHP编写一个正则表达式来验证以下内容:
我已经看过几乎所有可以找到的参考资料,但无济于事。
我想我可以单独测试,但这让我很伤心:(
有人可以帮忙吗? (然后把我送到一个我可以用普通英语Reg Ex学习的地方?)
答案 0 :(得分:8)
(这是很多熵)
(图片来自XKCD)
考虑到这一点,您可能需要考虑删除规则2& 3如果密码长度高于X(例如20)或将最小值增加到至少16个字符(作为唯一规则)。
至于你的要求:
与拥有一个大型,丑陋,难以维护的高级RegExp相反,您可能希望在较小的部分中解决问题,并使用专用功能分别处理每个位。
为此,您可以查看ctype_*
functions,count_chars()和MultiByte String Functions。
现在丑陋的:
此高级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)
并将$upper
中的字符数计为两个以上。
第三次 LookAhead使用一个字符类:[\x20-\x40\x5b-\x60\x7b-\x7e\x80-\xbf]
,其中包含常用符号的十六进制转义字符范围(几乎所有符号都可以在普通键盘上找到)。您也可以改为$sym=preg_replace('/[^a-zA-Z]/','',$string)
并将$sym
中的字符数计为两个以上。 注意:为了缩短它,我使用递归组(?1)
不再重复相同的字符类
对于学习,我所知道的最全面的RegExp参考是:regular-expressions.info
答案 1 :(得分:1)
您可以使用前瞻来确保您正在寻找的内容得到适当的包含。
/(?=.*[A-Z].*[A-Z])(?=.*[^a-zA-Z].*[^a-zA-Z]).{10,}/
答案 2 :(得分:1)
我总是喜欢用旧的程序代码来处理这样的东西。正则表达式可能很有用,但它们也有点麻烦,特别是对于代码维护和快速扫描(正则表达式不是可读性的确切示例)。
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;
}