Mohit Agrawal
Mohit Agrawal

Reputation: 323

Regex to validate at least two character classes (letters, number , special characters)

I want to match at least two character classes in java for a input string that contains only small letters[a-z], capital letters[A-Z], numbers[0-9], special characters [!#+,-./:=@] .

I have arrived at the below mentioned regex but it's not working :

((?=.*[a-z])(?=.*[A-Z]))|((?=.*[a-z])(?=.*[\\d]))|((?=.*[A-Z])(?=.*[\\d]))|((?=.*[!#+,.\\=:=@-])(?=.*[\\d]))|((?=.*[!#+,.\\=:=@-])(?=.*[a-z]))|((?=.*[!#+,.\\=:=@-])(?=.*[A-Z]))

Examples :

wel123 - valid
123@@! - valid
@@@aaa - valid
!!!BDC - valid
ABC123 - valid
rrirrra - invalid
1234567 - invalid
ABCFESS - invalid
@@@!!!! - invalid

Thanks in advance.

Upvotes: 0

Views: 729

Answers (2)

Pushpesh Kumar Rajwanshi
Pushpesh Kumar Rajwanshi

Reputation: 18357

The only thing missing in your regex is adding start ^ and $ end anchors and grouping whole of your regex properly. I've also removed unnecessary grouping from your regex and you can use this regex,

^(?:(?=.*[a-z])(?=.*[A-Z])|(?=.*[a-z])(?=.*[\d])|(?=.*[A-Z])(?=.*[\d])|(?=.*[!#+,.\\=:=@-])(?=.*[\d])|(?=.*[!#+,.\\=:=@-])(?=.*[a-z])|(?=.*[!#+,.\\=:=@-])(?=.*[A-Z])).+$

Regex Demo

Although this approach works but I'll suggest you to write a code for achieving this, as this regex may not be maintainable for people in general.

Java Code approach to validate strings rather than pure big regex

Following is an approach using Java codes, where you can pass a List of patterns to a method, along with the string to be validated and a number which is the minimum patterns required to match. Check this code,

public static void main(String[] args) {
    int minRequiredMatch = 2;
    List<String> list = Arrays.asList("wel123","123@@!","@@@aaa","!!!BDC","ABC123","rrirrra","1234567","ABCFESS","@@@!!!!");

    list.forEach(x -> {
        System.out.println(x + " - " + (validateTwoCharSets(x, minRequiredMatch)?"Valid":"Invalid"));
    });
}

public static boolean validateTwoCharSets(String str, int minRequiredMatch) {
    List<Pattern> patList = new ArrayList<>();
    patList.add(Pattern.compile("[a-z]"));
    patList.add(Pattern.compile("[A-Z]"));
    patList.add(Pattern.compile("[0-9]"));
    patList.add(Pattern.compile("[!#+,-./:=@]"));

    return validateTwoCharSets(patList, str, minRequiredMatch);
}

public static boolean validateTwoCharSets(List<Pattern> patList, String str, int minRequiredMatch) {
    if (minRequiredMatch <0 || minRequiredMatch > patList.size()) {
        throw new RuntimeException("minRequiredMatch must be a positive number and not more than pattern list size.");
    }
    int matchCount = 0;

    for (Pattern p : patList) {
        Matcher m = p.matcher(str);
        if (m.find()) {
            matchCount++;
        }
        if (matchCount >= minRequiredMatch) {
            return true;
        }
    }

    return false;
}

For your given data set prints following,

wel123 - Valid
123@@! - Valid
@@@aaa - Valid
!!!BDC - Valid
ABC123 - Valid
rrirrra - Invalid
1234567 - Invalid
ABCFESS - Invalid
@@@!!!! - Invalid

Upvotes: 3

Highbrainer
Highbrainer

Reputation: 760

I understand that you want a regex that matches any string that contains at least 2 consecutive characters from the set you defined.

I'd go with this :

.*[\w\d!#+,-./:=@]{2}.*

See full code :

package so20190502;

public class TwoOrMoreChars {

    public TwoOrMoreChars() {
    }

    public boolean matches(String s) {
        return s.matches(".*[\\w\\d!#+,-./:=@]{2}.*");
    }

    private void testString(String s) {
        System.out.println("String '" + s + "' does " + (matches(s)?"":"NOT") + " match.");
    }

    public static void main(String[] args) {
        TwoOrMoreChars me = new TwoOrMoreChars();
        me.testString("1");
        me.testString("1%2");
        me.testString("1%2%a%-%'");
        me.testString("1%2a-'");
    }

}

This outputs :

String '1' does NOT match.
String '1%2' does NOT match.
String '1%2%a%-%'' does NOT match.
String '1%2a-'' does  match.

HTH!

Upvotes: 0

Related Questions