简体   繁体   English

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

[英]Regex match 2 out of 4 groups

I want a single Regex expression to match 2 groups of lowercase, uppercase, numbers or special characters. 我希望单个Regex表达式匹配2组小写,大写,数字或特殊字符。 Length needs to also be grater than 7. 长度也需要大于7。

I currently have this expression 我目前有这个表达方式

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

It, however, forces the string to have lowercase and uppercase and digit or special character. 但是,它强制字符串具有小写和大写以及数字或特殊字符。

I currently have this implemented using 4 different regex expressions that I interrogate with some C# code. 我目前使用4个不同的正则表达式实现了这个,我用一些C#代码询问。

I plan to reuse the same expression in JavaScript. 我计划在JavaScript中重用相同的表达式。

This is sample console app that shows the difference between 2 approaches. 这是示例控制台应用程序,显示了两种方法之间的差异。

class Program
{
    private static readonly Regex[] Regexs = new[] {
        new Regex("[a-z]", RegexOptions.Compiled), //Lowercase Letter
        new Regex("[A-Z]", RegexOptions.Compiled), // Uppercase Letter
        new Regex(@"\d", RegexOptions.Compiled), // Numeric
        new Regex(@"[^a-zA-Z\d\s:]", RegexOptions.Compiled) // Non AlphaNumeric
    };

    static void Main(string[] args)
    {
        Regex expression = new Regex(@"^(?=.*[^a-zA-Z])(?=.*[a-z])(?=.*[A-Z]).{8,}$", RegexOptions.ECMAScript & RegexOptions.Compiled);

        string[] testCases = new[] { "P@ssword", "Password", "P2ssword", "xpo123", "xpo123!", "xpo123!123@@", "Myxpo123!123@@", "Something_Really_Complex123!#43@2*333" };

        Console.WriteLine("{0}\t{1}\t", "Single", "C# Hack");
        Console.WriteLine("");
        foreach (var testCase in testCases)
        {
            Console.WriteLine("{0}\t{2}\t : {1}", expression.IsMatch(testCase), testCase, 
                    (testCase.Length >= 8 && Regexs.Count(x => x.IsMatch(testCase)) >= 2));
        }

        Console.ReadKey();
    }
}

Result  Proper     Test String
------- -------    ------------

True    True     : P@ssword
False   True     : Password
True    True     : P2ssword
False   False    : xpo123
False   False    : xpo123!
False   True     : xpo123!123@@
True    True     : Myxpo123!123@@
True    True     : Something_Really_Complex123!#43@2*333

For javascript you can use this pattern that looks for boundaries between different character classes: 对于javascript,您可以使用此模式查找不同字符类之间的边界:

^(?=.*(?:.\b.|(?i)(?:[a-z]\d|\d[a-z])|[a-z][A-Z]|[A-Z][a-z]))[^:\s]{8,}$

if a boundary is found, you are sure to have two different classes. 如果找到边界,你肯定有两个不同的类。

pattern details: 图案细节:

\b # is a zero width assertion, it's a boundary between a member of 
   # the \w class and an other character that is not from this class.

.\b. # represents the two characters with the word boundary.

boundary between a letter and a number: 字母和数字之间的边界:

(?i) # make the subpattern case insensitive
(?:
    [a-z]\d # a letter and a digit
  |         # OR
    \d[a-z] # a digit and a letter
)

boundary between an uppercase and a lowercase letter: 大写和小写字母之间的边界:

[a-z][A-Z] | [A-Z][a-z]

since all alternations contains at least two characters from two different character classes, you are sure to obtain the result you hope. 由于所有替换都包含来自两个不同角色类的至少两个字符,因此您一定会获得您希望的结果。

You could use possessive quantifiers (emulated using atomic groups), something like this: 您可以使用所有格量词(使用原子组模拟),如下所示:

((?>[a-z]+)|(?>[A-Z]+)|(?>[^a-zA-Z]+)){2,}

Since using possessive matching will prevent backtracking, you won't run into the two groups being two consecutive groups of lowercase letters, for instance. 因为使用所有格匹配会阻止回溯,所以你不会遇到两组连续的小写字母组。 So the full regex would be something like: 所以完整的正则表达式将是这样的:

^(?=.*((?>[a-z]+)|(?>[A-Z]+)|(?>[^a-zA-Z]+)){2,}).{8,}$

Though, were it me, I'd cut the lookahead, just use the expression ((?>[az]+)|(?>[AZ]+)|(?>[^a-zA-Z]+)){2,} , and check the length separately. 虽然,是我,我会削减前瞻,只需使用表达式((?>[az]+)|(?>[AZ]+)|(?>[^a-zA-Z]+)){2,} ,并分别检查长度。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM