匹配四个正则表达式要求中至少三个的最佳方法

时间:2014-11-18 10:12:24

标签: javascript regex

在密码策略中,有4个要求。 它应包含以下任何三个

  1. 小写。
  2. 大写。
  3. 数字。
  4. 特殊字符。
  5. 以下正则表达式将匹配所有情况

    ^(?=.*\d)(?=.*[a-z])(?=.*[A-Z])(?=.*[^a-zA-Z0-9]).{4,8}$
    

    我知道我可以使用' |'然而,声明所有组合将产生一个超长的正则表达式。替换' |'的最佳方式是什么?这样它可以检查输入是否包含组合中的三个条件中的任何一个?

2 个答案:

答案 0 :(得分:3)

如果您正在使用PCRE风格,则以下内容可以满足您的需求(为便于阅读而格式化)

^(?:
    ((?=.*\d))((?=.*[a-z]))((?=.*[A-Z]))((?=.*[^a-zA-Z0-9]))|
    (?1)      (?2)         (?3)                             |
    (?1)      (?2)                      (?4)                |
    (?1)                   (?3)         (?4)                |
              (?2)         (?3)         (?4)
).{4,8}$

Regular expression visualization

一衬里:

^(?:((?=.*\d))((?=.*[a-z]))((?=.*[A-Z]))((?=.*[^a-zA-Z0-9]))|(?1)(?2)(?3)|(?1)(?2)(?4)|(?1)(?3)(?4)|(?2)(?3)(?4)).{4,8}$

Debuggex上的演示


JavaScript regex flavor不支持递归(实际上它不支持很多东西)。更好地使用4种不同的正则表达式,例如:

var validate = function(input) {
    var regexes = [
        "[A-Z]",
        "[a-z]",
        "[0-9]",
        "[^a-zA-Z0-9]"
    ];    
    var count = 0;
    for (var i = 0, n = regexes.length; i < n; i++) {
        if (input.match(regexes[i])) {
            count++;
        }
    }    
    return count >=3 && input.match("^.{4,8}$");    
};

答案 1 :(得分:1)

当然,这是一种方法,它使用相同的正则表达式的略微修改,但需要一小段代码创作。

^(?=(\D*\d)|)(?=([^a-z]*[a-z])|)(?=([^A-Z]*[A-Z])|)(?=([a-zA-Z0-9]*[^a-zA-Z0-9])|).{4,8}$

这里有五个捕获组 - 检查其中至少有三个是否为空。捕获的空组有效地表示前瞻中的替代方案已匹配,并且左侧的捕获组无法匹配。

例如,在PHP中:

preg_match("/^(?=(\\D*\\d)|)(?=([^a-z]*[a-z])|)(?=([^A-Z]*[A-Z])|)(?=([a-zA-Z0-9]*[^a-zA-Z0-9])|).{4,8}$/", $str, $matches);

$count = -1; // Because the zero-eth element is never null.
foreach ($matches as $element) {
    if ( !empty($element)) {
        $count += 1;
    }
}

if ($count >= 3) {
    // ...
}

或Java:

Matcher matcher = Pattern.compile(...).matcher(string);

int count = 0;

if (matcher.matches())
    for (int i = 1; i < 5; i++)
        if (null != matcher.group(i))
            count++;

if (count >= 3)
    // ...