[英]What is the Regular expression for following constraint?
我想要一個密碼字符串的正則表達式,該字符串至少包含以下四種字符中的三種:
並且應該包含至少 8 個字符。
鑒於這些要求可能會產生巨大的影響,我懷疑您實際上最好將其作為多項檢查進行,例如(偽代碼):
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你要么最終得到一個巨大的前瞻正則表達式,要么得到一個包含由|
分隔的十六種排序可能性的單個正則表達式。 .
這些都不可能像簡單的代碼段那樣高效或可讀。
正則表達式的擴展 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
首先,這里是 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 類:
^
(?=.*\p{Ll}(?<Counter>))?
(?=.*\p{Lu}(?<Counter>))?
(?=.*\p{Nd}(?<Counter>))?
(?=.*[\p{S}\p{P}](?<Counter>))?
(?<-Counter>){3}
.{8}
組合學並沒有那么糟糕——只有四種方法可以從四種可能性中選擇三種; 您可以在正則表達式的開頭使用前瞻測試那些,然后檢查八個字符與實際匹配:
^(?:(?=.*[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}
我的問題的正確答案:
正則表達式:
^((?=.[\d])(?=.[az])(?=.[AZ])|(?=.[az])(?=.[AZ])(?=.[^ \w\d\s])|(?=.[\d])(?=.[AZ])(?=.[^\w\d\s])|(?=.[\d]) (?=.[az])(?=.[^\w\d\s])).{8,30}$
謝謝。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.