用于检查 4 个不同字符组中的至少 3 个的正则表达式

Posted

技术标签:

【中文标题】用于检查 4 个不同字符组中的至少 3 个的正则表达式【英文标题】:Regex for checking that at least 3 of 4 different character groups exist 【发布时间】:2011-08-22 11:41:03 【问题描述】:

我正在尝试编写密码验证器。

如何查看我提供的字符串是否包含至少 3 个不同的字符组?

检查它们是否存在很容易——但至少有 3 个?

至少八 (8) 个字符

至少三个不同的字符组

大写字母

小写字母

数字

特殊字符 !@#$%&/=?_.,:;-\

(我正在使用 javascript 进行正则表达式)

【问题讨论】:

顺便说一句,@Yonder,你为什么只需要一个正则表达式?你想把它放到一些 JS 验证控件上吗? 【参考方案1】:

只是为了学习 - 这种要求是否可以在纯正则表达式中实现?

这将使它成为一个相当难以阅读(并因此维护!)的解决方案,但它是:

(?mx)
^
(
  (?=.*[a-z])(?=.*[A-Z])(?=.*[0-9])                # must contain a-z, A-Z and 0-9
  |                                                # OR
  (?=.*[a-z])(?=.*[A-Z])(?=.*[!@\#$%&/=?_.,:;\\-]) # must contain a-z, A-Z and special
  |                                                # OR
  (?=.*[a-z])(?=.*[0-9])(?=.*[!@\#$%&/=?_.,:;\\-]) # must contain a-z, 0-9 and special
  |                                                # OR
  (?=.*[A-Z])(?=.*[0-9])(?=.*[!@\#$%&/=?_.,:;\\-]) # must contain A-Z, 0-9 and special
)
.8,                                              # at least 8 chars
$

一个(可怕的)Javascript 演示:

var pw = "aa$aa1aa";
if(pw.match(/^((?=.*[a-z])(?=.*[A-Z])(?=.*[0-9])|(?=.*[a-z])(?=.*[A-Z])(?=.*[!@#$%&\/=?_.,:;\\-])|(?=.*[a-z])(?=.*[0-9])(?=.*[!@#$%&\/=?_.,:;\\-])|(?=.*[A-Z])(?=.*[0-9])(?=.*[!@#$%&\/=?_.,:;\\-])).8,$/)) 
  print('Okay!');
 else 
  print('Fail...');

打印:Okay!,您可以在 Ideone 上看到。

【讨论】:

顺便说一句,我一直希望正则表达式能够存储模式。我发现自己多次重复使用模式,因为它不是一个有意义的选择。基本上,类似(?\A[a-z])\A 分配给[a-z]。我猜我会继续做梦。 @Brad,这一个好主意。当然,您可以从字符串构建您的模式并将它们连接起来并执行new RegExp(a+"@"+a),其中a 是预定义的模式字符串。 (但你可能已经意识到了......) @BartKiers:这就是我一直在做的,只是为了便于维护,但很高兴看到“正则表达式宏”。也许在模式的开头强制定义,然后允许在该模式的持续时间内使用。 ;-) @Brad,许多正则表达式爱好者会欢迎这种诡计(像我一样),但是,正如您可能知道的那样,对于每个正则表达式爱好者来说,可能有大约 10 人反对引入这种简短的-切入已经“难以阅读”的语言。 :) @BartKiers:我同意,我们需要带回:labelsgotos 吗?而且您知道他们对使用正则表达式解决问题的看法:now you have two problems。 :咧嘴:【参考方案2】:

也可以参与其中:

String.prototype.isValidPW = function()   
    // First, check for at least 8 characters
    if (this.length < 8) return false;

    // next, check that we have at least 3 matches
    var re = [/\d/, /[A-Z]/, /[a-z]/, /[!@#$%&\/=?_.,:;-]/], m = 0;
    for (var r = 0; r < re.length; r++)
        if ((this.match(re[r]) || []).length > 0) m++;
    

    return m >= 3;
;

if ("P@ssW0rd".isValidPW()) alert('Acceptable!');

Demo

【讨论】:

不错的一个。请注意,您无需在字符类中转义 .$? @BartKiers:有趣的故事:我偶然逃脱了] 并且遇到了 JS 错误。有点困惑,模式没有被接受,我逃避了一切,一个一个地删除了`s。然后,头被抓了之后,我抓住了它,忘了躲开其余的东西。 :oops: ;-) 最酷的不是把它放在 String.proto 中,而是放在另一个对象中。并且还创建一次这些正则表达式,例如:jsfiddle.net/XnPb4 这是我最喜欢的解决方案,但所提供的解决方案都不能确保所有字符都是可接受的类型。例如,单引号 (') 会提示“可接受!”这里。我的快速解决方法是将返回更改为:return (m &gt;= 3 &amp;&amp; this.match(/^[0-9a-zA-Z!@#$%&amp;\/=?_.,:;-]+$/));【参考方案3】:

我假设您将针对不同的要求使用不同的正则表达式。在这种情况下,请告诉我以下内容是否适合您:

var e = password.match(/.8,/); //At least 8 chars

var a = password.match(/[0-9]+/); //numeric
var b = password.match(/[A-Z]+/); //Capitals
var c = password.match(/[a-z]+/); //small letters
var d = password.match(/[!@#\$%&/=?_.,:;-\\]+/); //special chars

if (a + b + c + d > 2 && e) // Success
else // Failure

【讨论】:

非常好用且简单易懂的解决方案。非常可读。谢谢。 只是为了学习 - 这种要求是否可以在纯正则表达式中实现? @Yonder:是和不是。您可以验证它是否具有[A-Z][a-z][0-9][&lt;special&gt;],但不是 4 个中有 3 个(据我所知),而不会将其分解为单独的功能。 顺便说一句 - 是否有必要在放入字符类时转义字符,即。在 [] 括号中? @Yonder:只有对正则表达式有意义的字符。例如句点 (.) 表示“任何字符”,因此当您需要文字句点时,您可以使用 \.$(行尾)、/(在这种情况下是因为它是模式包装器)、?(表示字符是可选的或不贪婪的标志)、- 在一个类中([])表示相同范围,因此您可以在课程结束时使用它或将其转义,等等。【参考方案4】:

http://jsfiddle.net/aSsR8/6/

/**
 * Function determine, wheter we have valid password
 * 
 * @param String value
 * @return Boolean
 */
function isValidPassword(value) 
    // Here we define all our params
    var validLength = 8,
        minSuccess  = 3,
        isNumeric   = + /\d+/.test(value),
        isCapitals  = + /[A-Z]+/.test(value),
        isSmall     = + /[a-z]+/.test(value),
        isSpecial   = + /[!@#$%&\/=\?_\.,:;\-]+/.test(value);

    if (value.length < validLength)  // 8 symbols. We don`t need regexp here
        return false;
    

    if (isNumeric + isCapitals  + isSmall + isSpecial < minSuccess) 
        return false;
    

    return true;



document.writeln(isValidPassword('abc'));
document.writeln(isValidPassword('abc123ABC'));
document.writeln(isValidPassword('abc123!23'));

【讨论】:

从什么时候... = + ...在赋值后使用算术运算符? 这是将类型转换为 int 的简写。我昨天在这里的某个地方看到了它:)【参考方案5】:

Crimson 的回答对我不起作用。这是我所拥有的。

var mystring = 'bLahbla\\';
var valid_char_count = 0;
var lc = mystring.match(/[a-z]+/);
var uc = mystring.match(/[A-Z]+/);
var dc = mystring.match(/[0-9]+/);
var sc = mystring.match(/[\!\@\#\$\%\&\=\?\_\.\,\:\;\-\\]/);

if( lc ) valid_char_count++; 
if( uc ) valid_char_count++; 
if( dc ) valid_char_count++; 
if( sc ) valid_char_count++; 

if( valid_char_count >= 3 ) /* success */ 

【讨论】:

【参考方案6】:

这将在一个正则表达式中完成所有这些

^.*(?=.8,)(?=.*[a-z])(?=.*[A-Z])(?=.*[\d\W])(?=.*[!@#\$%&amp;/=?_\.,:;-\\]).*$

【讨论】:

我应该补充一点,IE6 不支持前瞻 对我来说没有四分之三。此模式可接受“密码”和“密码”(缺少数字或特殊字符才有效)。 这个似乎对我有用...密码和密码对我来说失败了,但 PassW0rd 成功 IE6 确实支持前瞻;这只是马车,@ 987654321@。我不知道这是否已经修复,但我很确定它至少在 IE7 中仍然被破坏。解决方法是在其他前瞻之前进行最小长度检查 - (?=.8,) - 您已经在做。 您是否需要两个 .* 模式匹配(1 个在前瞻之前,1 个在它们之后)?看来您只需要 1 '.*' 在 ^ 和 $ 之间。此外,这并不能确保您有 4 个课程中的 3 个。你**必须**有一个大写字符和一个小写字符;你必须至少有一个数字或特殊字符。例如,'pa$$w0rd' 不会匹配,即使它有 3 个类。

以上是关于用于检查 4 个不同字符组中的至少 3 个的正则表达式的主要内容,如果未能解决你的问题,请参考以下文章

具有不同量词的正则表达式捕获组

正则表达式匹配 4 个组中的 2 个

正则表达式,用于包含至少8个字符和至少1个非字母数字字符的密码

包含至少 8 个字符和至少 1 个非字母数字字符的密码的正则表达式

正则表达式查找 4 个条件中的 3 个

密码正则表达式 [关闭]