Java String.Matches(); [duplicate] - 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.

Related

Password validation, one regex pattern at a time

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.

Regex check to see if a String contains non digit fails

Why does this fail?
String n = "h107";
if (n.matches("\\D+")) {
System.out.println("non digit in it");
}
I had a night sleep over it, and I still not get it.
I got a solution now:
if (n.matches(".*\\D+.*")) {
But in my (maybe lack of knowledge) the first one should also match. Cause if it has to match a complete String, then what's the point of a '^' character for a line beginning.
That is the recurring problem of .matches(): it is misnamed. It does NOT do regex matching. And the problem is that even other languages have fallen prey to that misnaming (python is one example).
The problem is that it will try to match your whole input.
Use a Pattern, a Matcher and .find() instead (.find() does real regex matching, ie find text that matches anywhere in the input):
private static final Pattern NONDIGIT = Pattern.compile("\\D");
// in code
if (NONDIGIT.matcher(n).find())
// there is a non digit
You should in fact use a Pattern; String's .matches() will recompile a pattern each time. With a Pattern it is only compiled once.
String.matches returns true if the entire string matches the pattern. Simply change your regular expression to \d+ which returns true if entire string consists of digits:
String n = "h107";
if (!n.matches("\\d+")) {
System.out.println("non digit in it");
}

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.util.regex.Matcher.replaceAll replacing without a match?

According to the javadoc:
Replaces every subsequence of the input sequence that matches the pattern with the given replacement string.
This seems to indicate that this call will not replace, unless a match is made.
And yet:
public class MisMatch {
public static void main(String args[]){
Pattern doubleSlash = Pattern.compile("\\\\");
String stringWithSingleSlash = "maybe\\no";
System.out.println("Matches:"+doubleSlash.matcher(stringWithSingleSlash).matches());
String replace = doubleSlash.matcher(stringWithSingleSlash).replaceAll("ABC");
System.out.println(replace);
System.out.println("Equal:"+(stringWithSingleSlash.equals(replace)));
}
}
This prints:
Matches:false
maybeABCno
Equal:false
so it is not matching, but still replacing. What am I missing here?
matches on returns true if the whole string matches - it doesn't match substrings.
So if stringWithSingleSlash were just "\\" instead of "mabye\\no", matches would return true.
If the fact that doubleSlash matches a single backslash confuses you, the explanation is that "\\\\" is a string with two backslashes and the regex engine interprets two backslashes as one escaped backslash (because the backslash is an escape character in regexes as well as in string literals).
The matches() function attempts to match the pattern against the entire string.
It seems like what you should use is to check if .find() returns true.
Take a look at the Matcher javadoc, here's an excerpt:
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.
Each of these methods returns a
boolean indicating success or failure.
More information about a successful
match can be obtained by querying the
state of the matcher.

Regex for java's String.matches method?

Basically my question is this, why is:
String word = "unauthenticated";
word.matches("[a-z]");
returning false? (Developed in java1.6)
Basically I want to see if a string passed to me has alpha chars in it.
The String.matches() function matches your regular expression against the whole string (as if your regex had ^ at the start and $ at the end). If you want to search for a regular expression somewhere within a string, use Matcher.find().
The correct method depends on what you want to do:
Check to see whether your input string consists entirely of alphabetic characters (String.matches() with [a-z]+)
Check to see whether your input string contains any alphabetic character (and perhaps some others) (Matcher.find() with [a-z])
Your code is checking to see if the word matches one character. What you want to check is if the word matches any number of alphabetic characters like the following:
word.matches("[a-z]+");
with [a-z] you math for ONE character.
What you’re probably looking for is [a-z]*

Categories

Resources