Password validation, one regex pattern at a time - java

For the password field, I have a TextWatcher, and onTextChanged, i run the each of four regex patterns against the text, one at a time. My regex patterns are:
".{3,5}"
"(?=.*[A-Z])"
"(?=.*[a-z])"
"(?=.*\\d)"
I wrote this test code and do not understand why this would fail:
Pattern pat = Pattern.compile("(?=.*[A-Z])");
Matcher mat = pat.matcher("aB");
if(mat.matches()){
System.out.println("MATCHES!");
}
else{
System.out.println("DOES NOT MATCH");
}
I expected a match here, but its failed.
Likewise other regex patterns also fail.

With look-around (?=condition) we can check many conditions on entire string, because it is zero-width (it will reset position of cursor in regex engine to place where it was right before test performed by look-ahead).
So since matches() checks if entire string matches regex, and look-around reset cursor it means that cursor wasn't able to pass entire string to accept this regex.
If you want to use matches() you can use regex like this
(?=.*[A-Z])(?=.*[a-z])(?=.*\\d).{3,5}
.{3,5} part will allow regex engine iterate over 3-5 characters, so if string is shorter, or longer it will not be accepted (because regex wasn't able to match entire string).
Alternative to this solution is to use find() instead of matches(). Also in that case you shouldn't use look-around. Simple [A-Z], [a-z], \\d with find() should be fine. We use look-around mechanisms only if we want regex to be able to iterate over data more than once.

Related

Regex: Match group if present otherwise ignore and proceed with other matches

I have been trying to match a regex pattern within the following data:
String:
TestData to 1colon delimiter list has 1 rows.Set...value is: 1 Save Error: 267467374736437-TestInfo send Error
Words to match:
TestData
267467374736437-TestInfo
Regex pattern i m using:
(.+?\s)?.*(\s\d+-.*?\s)?
Scenario here is that 2nd match (267467374736437-TestInfo) can be absent in the string to be matched. So, i want it to be a match if it exists otherwise proceed with other matches. Due to this i added zero or one match quantifier ? to the group pattern above. But then it ignores the 2nd group all together.
If i use the below pattern:
`(.+?\s)?.*(\s\d+-.*?\s)`
It matches just fine but fails if string "267467374736437-TestInfo" from the matching string as it's not having the "?" quantifier.
Please help me understand where is it going wrong.
I would rather not use a complex regex, which will be ugly and a maintenance nightmare. Instead, one simple way would be to just split the string and grab the first term, and then use a smart regex to pinpoint the second term.
String input = "TestData to 1colon delimiter list has 1 rows.Set...value is: 1 Save Error: 267467374736437-TestInfo send Error";
String first = input.split(" ")[0];
String second = input.replaceAll(".*Save Error:\\s(.*)?\\s", "$1");
Explore the regex:
Regex101
The optional pattern at the end will almost never not be matched if a more generic pattern occurs. In your case, the greedy dot .* grabs the whole rest of the line up to the end, and since the last pattern is optional, the regex engine calls it a day and does not try to accommodate any text for it.
If you had a lazy dot .*?, the only position where it would work is right after the preceding subpattern, which is rarely the case.
Thus, you can only rely on a tempered greedy token:
^(\S+)(?:(?!\d+-\S).)*(\d+-\S+)?
See the regex demo.
Or an unrolled version:
^(\S+)\D*(?:\d(?!\d*-\S)\D*)*(\d+-\S+)?

Java String.Matches(); [duplicate]

if("test%$#*)$(%".matches("[^a-zA-Z\\.]"))
System.exit(0);
if("te/st.txt".matches("[^a-zA-Z\\.]"))
System.exit(0);
The program isn't exiting even though the regexes should be returning true. What's wrong with the code?
matches returns true only if regex matches entire string.
In your case your regex represents only one character that is not a-z, A-Z or ..
I suspect that you want to check if string contains one of these special characters which you described in regex. In that case surround your regex with .* to let regex match entire string. Oh, and you don't have to escape . inside character class [.].
if ("test%$#*)$(%".matches(".*[^a-zA-Z.].*")) {
//string contains character that is not in rage a-z, A-Z, or '.'
BUT if you care about performance you can use Matcher#find() method which
can return true the moment it will find substring containing match for regex. This way application will not need to check rest of the text, which saves us more time the longer remaining text is.
Will not force us to constantly build Pattern object each time String#matches(regex) is called, because we can create Pattern once and reuse it with different data.
Demo:
Pattern p = Pattern.compile("[^a-zA-Z\\.]");
Matcher m = p.matcher("test%$#*)$(%");
if(m.find())
System.exit(0);
//OR with Matcher inlined since we don't really need that variable
if (p.matcher("test%$#*)$(%").find())
System.exit(0);
x.matches(y) is equivalent to
Pattern.compile(y).matcher(x).matches()
and requires the whole string x to match the regex y. If you just want to know if there is some substring of x that matches y then you need to use find() instead of matches():
if(Pattern.compile("[^a-zA-Z.]").matcher("test%$#*)$(%").find())
System.exit(0);
Alternatively you could reverse the sense of the test:
if(!"test%$#*)$(%".matches("[a-zA-Z.]*"))
by providing a pattern that matches the strings that are allowed rather than the characters that aren't, and then seeing whether the test string fails to match this pattern.
You obtain always false because the matches() method returns true only when the pattern matches the full string.

Why is String.matches returning false in Java?

if("test%$#*)$(%".matches("[^a-zA-Z\\.]"))
System.exit(0);
if("te/st.txt".matches("[^a-zA-Z\\.]"))
System.exit(0);
The program isn't exiting even though the regexes should be returning true. What's wrong with the code?
matches returns true only if regex matches entire string.
In your case your regex represents only one character that is not a-z, A-Z or ..
I suspect that you want to check if string contains one of these special characters which you described in regex. In that case surround your regex with .* to let regex match entire string. Oh, and you don't have to escape . inside character class [.].
if ("test%$#*)$(%".matches(".*[^a-zA-Z.].*")) {
//string contains character that is not in rage a-z, A-Z, or '.'
BUT if you care about performance you can use Matcher#find() method which
can return true the moment it will find substring containing match for regex. This way application will not need to check rest of the text, which saves us more time the longer remaining text is.
Will not force us to constantly build Pattern object each time String#matches(regex) is called, because we can create Pattern once and reuse it with different data.
Demo:
Pattern p = Pattern.compile("[^a-zA-Z\\.]");
Matcher m = p.matcher("test%$#*)$(%");
if(m.find())
System.exit(0);
//OR with Matcher inlined since we don't really need that variable
if (p.matcher("test%$#*)$(%").find())
System.exit(0);
x.matches(y) is equivalent to
Pattern.compile(y).matcher(x).matches()
and requires the whole string x to match the regex y. If you just want to know if there is some substring of x that matches y then you need to use find() instead of matches():
if(Pattern.compile("[^a-zA-Z.]").matcher("test%$#*)$(%").find())
System.exit(0);
Alternatively you could reverse the sense of the test:
if(!"test%$#*)$(%".matches("[a-zA-Z.]*"))
by providing a pattern that matches the strings that are allowed rather than the characters that aren't, and then seeing whether the test string fails to match this pattern.
You obtain always false because the matches() method returns true only when the pattern matches the full string.

JAVA equivalent to Javascript REGEX

I'm totally beginner in java.
In javascript i have this regex:
/[^0-9.,\-\ ]/gi
How can i do the same in java?
Have a look at this: http://docs.oracle.com/javase/7/docs/api/java/util/regex/Pattern.html
Theres quite a lot you can do in Java with Regex
If you want to match repeatedly against that regex, you would do:
Pattern p = Pattern.compile("(?i)[^0-9.,-\ ]");
Matcher m = p.matcher(targetString);
Then use the matcher methods in a loop to get the match you want. The "i" is a case insensitivity flag (which you actually don't need as there are no characters specified), but I'm not sure what the equivalent of the "g" flag is.. I think it's simply to attempt to apply the pattern repeatedly to the target string rather than to try and match the whole string, which is what the above code does.
Also, the pattern above will only match one character at a time, you may in fact want [^0-9.,-\ ]*, which will match against 0 or more characters, greedily. I would read the docs on the Pattern class if I were you.

Java regex basic usage problem

The following code works:
String str= "test with foo hoo";
Pattern pattern = Pattern.compile("foo");
Matcher matcher = pattern.matcher(str);
if(matcher.find()) { ... }
But this example does not:
if(Pattern.matches("foo", str)) { ... }
And neither this version:
if(str.matches("foo")) { ... }
In the real code, str is a chunk of text with multiple lines if that is treated differently by the matcher, also in the real code, replace will be used to replace a string of text.
Anyway, it is strange that it works in the first version but not the other two versions.
Edit
Ok, I realise that the behaviour is the same in the first example if if(matcher.matches()) { ... } is used instead of matcher.find. I still cannot make it work for multiline input but I stick to the Pattern.compile/Pattern.matcher solution anyway.
Your last couple of examples fail because matches adds an implicit start and end anchor to your regular expression. In other words, it must be an exact match of the entire string, not a partial match.
You can work around this by using .*foo.* instead. Using Matcher.find is more flexible solution though, so I'd recommend sticking with that.
In Java, String.matches delegates to Pattern.matches which in turn delegates to Matcher.matches, which checks if a regex matches the entire string.
From the java.util.regex.Matcher API:
Once created, a matcher can be used to perform three different kinds of match operations:
The matches method attempts to match the entire input sequence against the pattern.
The lookingAt method attempts to match the input sequence, starting at the beginning, against the pattern.
The find method scans the input sequence looking for the next subsequence that matches the pattern.
To find if a substring matches pattern, you can:
Matcher.find() the pattern within the string
Check if the entire string matches .*pattern.*
Related questions
On matches() matching whole string:
Why is my regex is not matching?
Java Regex Match Error
Java RegEx Pattern not matching (works in .NET)
On hitEnd() for partial matching:
How can I perform a partial match with java.util.regex.*?
Can java.util.regex.Pattern do partial matches?
On multiline vs singleline/Pattern.DOTALL mode:
string.matches(".*") returns false

Categories

Resources