Reputation: 323
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
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])).+$
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
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