簡體   English   中英

以下約束的正則表達式是什么?

[英]What is the Regular expression for following constraint?

我想要一個密碼字符串的正則表達式,該字符串至少包含以下四種字符中的三種:

  • 英文小寫字符(a 到 z)。
  • 英文大寫字符(A 到 Z)。
  • 以 10 位為基數(0 到 9)。
  • 非字母數字字符(例如,,$,#.%)。

並且應該包含至少 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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM