Matcher.matches() matches the complete string. You can use Matcher.find to match the individual integers:
while (m.find()) {
System.out.println(m.group(1));
}
Answer from Reimeus on Stack OverflowFirst time posting here, let me know if I need to edit post to conform to any rules. My issue is that I'm trying to match regex pattern to separate out the number of cubes drawn and its color but my Matcher object seems to not be returning any matches so it's throwing a no match found exception when I try to call digitMatcher.group(). I have tested my regex pattern on sites like regexr and it seems to pass there but it's not working for some reason here. I use the same type of regex on day one and it work there so I'm not sure where my regex pattern is failing here. I'm talking about specifically in my isGameValid() method where I create a matcher base on a pattern I made above. Through debugging I know that I separated the string color pairing correctly and that my Matcher object has the correct regex pattern, it's just not matching for some reason. Any help would be appreciated. Code below:
import java.io.File;
import java.io.FileNotFoundException;
import java.util.Scanner;
import java.util.Map;
import java.util.StringTokenizer;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import static java.lang.Integer.parseInt;
import static java.lang.Integer.sum;
public class dayTwoA {
public static final Map<String, Integer> map = Map.of( // Mapping of digits to their letter spelling.
"red", 12,
"green", 13,
"blue", 14
);
public static final Pattern colorPattern = Pattern.compile("blue|green|red");
public static final Pattern digitPattern = Pattern.compile("[0-9]|[0-9][0-9]");
public static int gameID = 0;
public static void main(String[] args) throws FileNotFoundException {
int sumGamesID = 0; // Sum of all the game ID.
// Create a scanner to get input from file.
Scanner inputFile = new Scanner(new File("src/dayTwoData.txt"));
// Parse file for data.
while (inputFile.hasNextLine()) {
String inputLine = inputFile.nextLine(); // Grab next line of input.
if (isGameValid(inputLine)) {
sumGamesID += gameID;
};
}
System.out.println("The sum of the ID of the games is " + sumGamesID);
}
private static boolean isGameValid(String inputLine) {
String gameDraws = inputLine.substring(inputLine.indexOf(":") + 1);
gameID++; // Increment game ID.
StringTokenizer separateDraw = new StringTokenizer(gameDraws, ";");
while (separateDraw.hasMoreTokens()) {
String draw = separateDraw.nextToken();
StringTokenizer numColor = new StringTokenizer(draw, ",");
while (numColor.hasMoreTokens()) {
String numColorPair = numColor.nextToken();
Matcher digitMatcher = digitPattern.matcher(numColorPair);
int numCubes = parseInt(digitMatcher.group());
Matcher colorMatcher = colorPattern.matcher(numColorPair);
String color = colorMatcher.group();
System.out.println(numCubes + "-" + colorMatcher.group());
if (numCubes > map.get(color)) {
return false;
}
System.out.println(numColorPair);
}
}
return true;
}
}Java regex does not match as expected - Stack Overflow
Java Regex pattern not matching - Stack Overflow
Java Pattern does not match RegEx - Stack Overflow
JAVA - Pattern regex matcher not matching - Stack Overflow
Matcher.matches() matches the complete string. You can use Matcher.find to match the individual integers:
while (m.find()) {
System.out.println(m.group(1));
}
Matcher.matches tells you if your regex matches the entire string. Your string isn't all digits. It contains letters, dots, equal signs, and square brackets. So you matcher doesn't match.
You want Matcher.find(). That searches for partial matches. Matcher.group then allows you to retrieve the matched portion of the input string.
Matcher.matchesreturnstrueonly if the ENTIRE region matches the pattern.For the output you are looking for, use
Matcher.findinstead
Explanation of each case:
Pattern p = Pattern.compile("[^A-Z]+");
Matcher matcher = p.matcher("GETs");
if (matcher.matches()) {
Fails because the ENTIRE region 'GETs' isn't lowercase
Pattern p = Pattern.compile("[A-Z]+");
Matcher matcher = p.matcher("GETs");
if (matcher.matches()) {
This fails because the ENTIRE region 'GETs' isn't uppercase
Pattern p = Pattern.compile("[A-Z]+");
Matcher matcher = p.matcher("GET");
if (matcher.matches()) {
The ENTIRE region 'GET' is uppercase, the pattern matches.
You're very first regex asks to match any character that is not in an uppercase range of A-Z. The match is on the lowercase "s" in GETs.
You can't ask a Matcher to give a .group() unless you have called a method which asks the Matcher to operate on the input: one of .find() (preferred), .lookingAt() or .matches().
This is why you get an IllegalStateException.
As to the differences between the three, while the javadoc tells it all, just a quick reminder:
.find()does "real" regex matching: it will try and match the regex anywhere in the input text;.lookingAt()adds the constraint that the pattern should match at the beginning of the input text;.matches()is a misnomer since in addition to the constraint imposed by.lookingAt(), it also required that the full input text (the "entire region" in the javadoc) is matched.
Please also recall that those three methods return a boolean depending on whether the match was successful; if the result is false, you can't .group().
You forgot to call m.find() or m.matches(). This is mandatory, otherwise group() does not work.
The find() should return true if the pattern is matched. Only in this case group() will return what you are expecting.
So, modify your code as following:
....
if (!m.find()) {
return;
}
String url = m.group();
...
EDIT
Concerning to what method to call: find() or matches().
find() looks for the pattern in part of string, matches() matches full string. They relate like contains() and equals() of strings.
I personally prefer to use find() because in this case the regex fully defines the behavior. If I want to match full string I use ^ and $.
See comments in the code and explanation below:
String cstring = "public class hello extends jframe ";
Pattern classPattern = Pattern.compile(".*?class\\s+(\\S+)\\s*"); // regex was changed a bit
Matcher m = classPattern.matcher(cstring);
//m.matches(); // <-- no need for that
if (m.find()) { // use find() instead of m.hitEnd()
System.out.println("found");
String className = m.group(1);
System.out.println(className);
}
OUTPUT
found
hello
Basically I removed the (public) from the regex and used the "1" matched group (zero is the whole expression in case there is a match). Your regex could be used as well, but then you'll have to use the seconded matched group as (public) will be come the first.
In addition to that I removed m.matches() which is not needed and replaced the m.hitEnd() with m.find() which should be used to iterate the matched results.
You need to call find() to make the engine find its match before trying to access it.
String s = "public class hello extends jframe";
Pattern p = Pattern.compile("public\\s*class\\s+(\\S+)");
Matcher m = p.matcher(s);
if (m.find()) {
System.out.println("found");
String className = m.group(1);
System.out.println(className);
}
Ideone Demo
You may add a |(.) alternative to your pattern (to match any char but a line break char) and check if Group 1 matched upon each match. If yes, output false, else, output true:
String argument = "#a1^b2";
Pattern pattern = Pattern.compile("[a-zA-Z]|[0-9]|\\s|(.)"); // or "[a-zA-Z0-9\\s]|(.)"
Matcher matcher = pattern.matcher(argument);
while(matcher.find()) { // find all matching characters
System.out.println(matcher.group(1) == null);
See the Java demo, output:
false
true
true
false
true
true
Note you do not need to use a Pattern.DOTALL here, because \s in your "whitelist" part of the pattern matches line breaks.
Why not simply removing all matching chars from your string, so you get only the non matching ones back:
import java.util.regex.Pattern;
import java.util.regex.Matcher;
public class RegexUtil {
public static void main(String[] args) {
String argument;
Pattern pattern;
Matcher matcher;
argument = "#a1^b2";
pattern = Pattern.compile("[a-zA-Z]|[0-9]|\\s");
matcher = pattern.matcher(argument);
// find all matching characters
while(matcher.find()) {
System.out.println(matcher.group());
argument = argument.replace(matcher.group(), "");
}
System.out.println("argument: " + argument);
}
}
Try calling
m.find();
after the .matcher statement.
It's throwing an exception because the pattern didn't match but you tried to get a group from it (m.matches() would be false here); groupCount() will return the number of groups that would be in a match, regardless of if there actually was one. As for why the match isn't working, Java Patterns match on the entire string, not on a substring
This will find all occurrences from your string.
final Pattern pattern = Pattern.compile(regex);
final Matcher matcher = pattern.matcher(string);
while (matcher.find()) {
System.out.println("Full match: " + matcher.group());
}
Can try this:
String text = "<style>templates/style/color.css</style>\n" +
"<style>templates/style/style.css</style>";
Pattern pattern = Pattern.compile("<style>(.+?)</style>");
Matcher matcher = pattern.matcher(text);
while (matcher.find()) {
System.out.println(text.substring(matcher.start(), matcher.end()));
}
Or:
Matcher matcher = pattern.matcher(text);
while (matcher.find()) {
System.out.println(matcher.group());
}
You need to call Matcher#find() to actually get a match:
Pattern p = Pattern.compile("([0-9]+)-([0-9]+)-([0-9]+)-([0-9]+)-([0-9]+)");
Matcher matcher = p.matcher("1-1-3-1-4");
if (matcher.find()) {
System.out.println(matcher.group(0))
}
If you were expecting multiple matches, you could use a while loop instead of an if statement.
Also note that you actually have five capture groups in your patterns. Capture groups are denoted by placing a portion of the pattern in parentheses. If you don't intend/need to capture the five separated numbers in your pattern individually, then you can consider telling the regex engine not to capture them, e.g. use this:
Pattern p = Pattern.compile("(?:[0-9]+)-(?:[0-9]+)-(?:[0-9]+)-(?:[0-9]+)-(?:[0-9]+)");
Demo
In Java regex index or study methods are used to return Matcher class matches:
if (matcher.matches()) {
System.out.println(matcher.group(0));
}
In the example above, the matches() "study" method attempts to match the entire region against the given pattern. Which method you use is generally indicative of what/how you want to match.
matches()
Attempts to match the entire region against the pattern.
find()
Attempts to find the next subsequence of the input sequence that matches the pattern.
Study methods review the input string and return a Boolean indicating whether or not the pattern is found
↳ http://docs.oracle.com/javase/tutorial/essential/regex/matcher.html
You first need to do
matcher.find()
to trigger the actual search. Usually like this:
Pattern pattern = Pattern.compile("(browse/)(.*)(\">)");
Matcher matcher = pattern.matcher(match);
if (matcher.find())
return matcher.group(1);
You should probably be using a different regex, though:
Pattern pattern = Pattern.compile("browse/([^<>\"]*)\">");
will be safer and more efficient (and provide the correct value in group number 1).
You have to call Matcher.find() or Matcher.matches() before you extract groups.
In your exact case you should call Matcher.find(), since your regex won't match against the entire input, which is what Matcher.matches() checks for.