規(guī)則如下:
密碼格式:6-16位數(shù)字字母組合
不包含特殊字符。
必須同時包含數(shù)字、大寫字母,小寫字母3種字符,區(qū)分大小寫。
連續(xù)3位及以上數(shù)字不能連續(xù)(例如123、876)
連續(xù)3位及以上的字母不能連續(xù)(例如abc、cba、aaa、111、AAA)
echo !preg_match('/\d{3,}|[a-zA-Z]{3,}/', $password); echo preg_match('/\d+/', $password); echo preg_match('/[a-z]+/', $password); echo preg_match('/[A-Z]+/', $password); echo preg_match('/^([a-zA-Z0-9]){6,16}$/', $password);
以上是需求和我想出來的解決方法
但是總想能用更簡潔的方式來匹配出來,希望有人能有更好的思路。
再問個問題:為什么正則表達式效率低?
因為連續(xù)的數(shù)字,字母用正則表達式判斷太復雜而且效率低,所以采用邏輯代碼判斷的方式,以下是我用PHP寫的代碼,php5.5.12 初步測試成功。
<?php define('PWD_MAX_LENGTH', 16); define('PWD_MIN_LENGTH', 6); /** * @time 2016年8月29日11:52:29 */ class User_Common { /** * 密碼格式:6-16位數(shù)字字母組合 * 不包含特殊字符。 * 必須同時包含數(shù)字、大寫字母,小寫字母3種字符,區(qū)分大小寫。 * 連續(xù)3位及以上數(shù)字不能連續(xù)(例如123、876) * 連續(xù)3位及以上的字母不能連續(xù)(例如abc、cba) * @param $password * @return bool * @throws \Exception */ public static function checkPassword($password) { self::pwdLengthCheck($password); self::pwdCharValid($password); } /** * @param $password * @return bool * @throws \Exception */ private static function pwdCharValid($password) { if (!ctype_alnum($password)) { throw new Exception('不包含特殊字符', 10002); } $includeNumber = false; $includeUpperLetter = false; $includeLowerLetter = false; $length = strlen($password); for ($i=0; $i < $length; $i++) { $char = $password[$i]; $includeUpperLetter = (!$includeUpperLetter && ctype_upper($char)) ? true : $includeUpperLetter; $includeNumber = (!$includeNumber && ctype_digit($char)) ? true : $includeNumber; $includeLowerLetter = (!$includeLowerLetter && ctype_lower($char)) ? true : $includeLowerLetter; if ($i != 0 && !empty($password[$i+1]) && abs(ord($password[$i]) - ord($password[$i-1])) <=1 && ord($password[$i]) - ord($password[$i-1]) == ord($password[$i+1]) - ord($password[$i])) { throw new Exception('連續(xù)3位及以上數(shù)字或字母不能連續(xù)(例如123、876)', 10004); } } if ($includeLowerLetter && $includeNumber && $includeUpperLetter) { return 2; } else { throw new Exception('必須同時包含數(shù)字、大寫字母,小寫字母3種字符,區(qū)分大小寫', 10003); } } private static function pwdLengthCheck($password) { if (strlen($password) > PWD_MAX_LENGTH || strlen($password) < PWD_MIN_LENGTH) { throw new Exception('密碼格式:6-16位數(shù)字字母組合', 10001); } } /** * 檢查是否為1開頭的11位數(shù)字手機號 * @param int $phoneNumber * @return boolean 是否匹配 */ public static function checkPhoneNumber($phoneNumber) { return preg_match('/^1\d{10}$/', $phoneNumber); } } try { var_dump(User_Common::checkPassword('AbA001')); } catch (Exception $e) { echo $e->getMessage(); }
擁有18年軟件開發(fā)和IT教學經(jīng)驗。曾任多家上市公司技術總監(jiān)、架構師、項目經(jīng)理、高級軟件工程師等職務。 網(wǎng)絡人氣名人講師,...
必須同時包含數(shù)字、大寫字母,小寫字母3種字符,區(qū)分大小寫。
/(?=.*\d)(?=.*[a-z])(?=.*[A-Z])/
為什么一定要使用正則,要知道這種問題用正則要寫多長,而且你寫的正則也不對。自己做遍歷不是更簡單高效嗎?
以下是偽代碼,語法請忽略:)
password?=?getPassword()??//獲取密碼 if?(password.length??16)?throw?長度錯誤;??//判斷長度 hasNumber?=?false hasUpper?=?false hasLower?=?false preDiff?=?0 preChar?=?null for?(char?in?password)?{??//遍歷取出字符 ??if?(!hasNumber)?hasNumber?=?isNumber(char);?//判斷是否包含數(shù)字 ??if?(!hasUpper)?hasUpper?=?isUpper(char);?//判斷是否包含大寫字母 ??if?(!hasLower)?hasLower?=?isLower(char);?//判斷是否包含小寫字母 ??if?(isSpecial(char))?throw?包含特殊字符;?//判斷是否包含特殊字符 ??diff?=?getDiff(preChar,?char);?//獲取字符的ASCII碼與上一個字符的差 ??//如果preDiff與diff差都為-1或1,則認為連續(xù) ??if?(abs(preDiff)?==?1?&&?preDiff?==?diff)?throw?字母或數(shù)字連續(xù)錯誤;?//可單獨判斷char求是字母還是數(shù)字連續(xù) ??preChar?=?char; ??preDiff?=?diff; }
在上例代碼中
6-16位數(shù)字字母組合
不包含特殊字符。
必須同時包含數(shù)字、大寫字母,小寫字母3種字符,區(qū)分大小寫。
應該都都看懂怎么判斷的,至于是否連續(xù)主要是利用字符的ASCII碼,并且0-9、a-z、A-Z在ASCII中是連續(xù)的。保存前兩個字符ASCII差與當前字符ASCII差來判斷是否三個連續(xù)。