Rihards
Rihards

Reputation: 10349

Regex: At least 2 symbols or numbers (or mixed) in Java

I know these questions are lame and make Stack Overflow like a regex dictionary, but I really would need some help with. It's like trying to understand hieroglyphs (at least for someone this is easy reputation).

I want to write a regex to check if password is at least 8 characters long and has at least 2 numbers or symbols (or mixed). The symbols probably can be the obvious ones [-+_!@#$%^&*.,?].

So I've come up with something like this so far: ^(?=.{8,})(?=.*\d{2,}).*$, but I can't understand how to put the symbols sequence in the \d part. Oh, I'm not sure if (?=) does work for Java, does it? This rubular.com/r/VC0ncbDlRl made writing regex little easier.

Upvotes: 1

Views: 4129

Answers (4)

Ryan Stewart
Ryan Stewart

Reputation: 128799

Another way to count numbers and specials that's "simpler" all around, using Commons Collections:

int matches = CollectionUtils.countMatches(
    passwordCharacters, new NumberOrSpecialCharacterPredicate());
return passwordCharacters.size() >= 8 && matches >= 2;

class NumberOrSpecialCharacterPredicate implements Predicate {
    private static final String symbols = "0123456789-+_!@#$%^&*.,?";
    public boolean evaluate(Object object) {
        return symbols.indexOf((Character) object) >= 0;
    }
}

Upvotes: 3

MRAB
MRAB

Reputation: 20654

How about this:

^(?=.{8,})(.*[-+_!@#$%^&*.,?0-9]){2,}

Upvotes: 0

Ryan Stewart
Ryan Stewart

Reputation: 128799

The other answer is a good one, but here's another way:

String password = "sn3arki7p";
char[] passwordCharacters = password.toCharArray();
Arrays.sort(passwordCharacters);
String sortedPassword = new String(passwordCharacters);
Pattern pattern = Pattern.compile("^(?=.{8,})(?=.*[-+_!@#$%^&*.,?0-9]{2,}).*$");
System.out.println(pattern.matcher(sortedPassword).matches());

Edit: Adjusted to require at least 2 of (number or special) instead of 2 number and 2 special.

Upvotes: 2

Martijn Courteaux
Martijn Courteaux

Reputation: 68847

That is not a job to do with a RegEx. In Java, it is so much simpler to write some custom code:

public static boolean isValidPassword(String pass)
{
    if (pass.length() < 8) return false;

    int symbolOrNumberCount = 0;
    String symbols = "0123456789-+_!@#$%^&*.,?";

    for (int i = 0; i < pass.length(); ++i)
    {
        if (symbols.indexOf((int) pass.charAt(i)) != -1)
        {
            symbolOrNumberCount++;
        }
    }

    return symbolOrNumberCount >= 2;
}

Upvotes: 4

Related Questions