1

There are lot of similar questions on the Regex, however I am still confused on the following case:

import java.util.regex.Pattern;

public class PatternTest {

  public static void main(String[] args) {
    String PATTERN = "((?=.*\\d)(?=.*[a-z])(?=.*[A-Z])(?=.*[@#$%]).{8,20})";
    Pattern pattern = Pattern.compile(PATTERN);

    boolean isTrue = pattern.matcher("nks#n1Kos2~([{&").matches();

    System.out.println(isTrue);
  }

}

The characters of ~([{& is not in the PATTERN, however the matches shows up true. What is the reason for that?

Here is a link on Java Regular Expression Tester https://www.freeformatter.com/java-regex-tester.html#ad-output

caot
  • 3,066
  • 35
  • 37
  • 2
    to help with confusion whet do `.{8,20}` match, yes ? not wise to restrict to set of characters for passwords. hackers guess that, combinations is doable –  May 28 '20 at 19:34

2 Answers2

2

The (?=X) patterns are "zero-width positive lookahead" assertions. So they're asserting that the regexes are found in the search string without consuming any of it. All of these assertions are passing successfully.

The .{8,20} pattern is saying "match any character as long as there are between 8 and 20 of them (inclusive)". So it is matching the entire string.

jb.
  • 9,921
  • 12
  • 54
  • 90
2

Your regex is:

String PATTERN = "(?=.*\\d)(?=.*[a-z])(?=.*[A-Z])(?=.*[@#$%]).{8,20}";

Which means match any character of 8 to 20 in length that fulfills all the conditions given in lookahead.

What you actually need is this:

String PATTERN = "(?=.*\\d)(?=.*[a-z])(?=.*[A-Z])(?=.*[@#$%])[a-zA-Z\\d@#$%]{8,20}";

[a-zA-Z\\d@#$%]{8,20} will match only allowed characters inside [...] 8 to 20 in length.

anubhava
  • 761,203
  • 64
  • 569
  • 643
  • 1
    `[a-zA-Z\\d@#$%]` works, however it's kind of clumsy for it needs to list all of the characters once more. – caot May 28 '20 at 19:30