Java Regex to match supplied word with special charcters - java

I am trying to match string by using Java Pattern class.
private boolean isMatch(String searchSentence, String matchWord) {
String patternText = ".*\\b";
Pattern pattern = Pattern.compile(patternText + matchWord + "\\b.*",Pattern.CASE_INSENSITIVE);
Matcher matcher = pattern.matcher(searchSentence);
return matcher.matches();
}
This will work if i have match string, which doesn't contains any special character like ({[ etc.
I am able to find "RANCH" but not "RANCH (EAGLEFORD)".
Few more examples
Let say my input string is: "Point [-99.73586,28.38092]" then i should be able to search for "-99.73586,28.38092"
Let say my input string is: "Point [-99.73586,28.38092]" then i should be able to search for "[-99.73586,28.38092]"
Let say my input string is: "Rench RenchY" then i should be able to search for "Rench" but RenchY Should not be the part of search result.
So how can i handle these type of case.

Example of using special characters ({}) in regex
String stringToSearch = "Some lengthy string I am trying to RANCH (EAGLEFORD) and RANCH {EAGLEFORD}";
Pattern p1 = Pattern.compile("RANCH\\s[(){}\\w]+");
Matcher m = p1.matcher(stringToSearch);
while (m.find())
{
System.out.println(m.group());
}
output:
RANCH (EAGLEFORD)
RANCH {EAGLEFORD}

If you plan to match your keywords not enclosed with word chars (letters, digits, or underscores), use (?<!\w) and (?!\w) lookarounds instead of \b.
private boolean isMatch(String searchSentence, String matchWord) {
Pattern pattern = Pattern.compile("(?<!\\w)" + Pattern.quote(matchWord) + "(?!\\w)", Pattern.CASE_INSENSITIVE);
Matcher matcher = pattern.matcher(searchSentence);
return matcher.find();
}
If you only plan to find matches enclosed with whitespace/start/end of string, use (?<!\S) and (?!\S) lookarounds:
private boolean isMatch(String searchSentence, String matchWord) {
Pattern pattern = Pattern.compile("(?<!\\S)" + Pattern.quote(matchWord) + "(?!\\S)", Pattern.CASE_INSENSITIVE);
Matcher matcher = pattern.matcher(searchSentence);
return matcher.find();
}
Do not forget to Pattern.quote your literal strings.
Using Matcher#find is preferable since you do not need the initial/trailing .* and eliminates unnecessary overhead related to regex backtracking mechanism.

Related

Java regex : find the last occurrence of a string using Matcher.matches()

I have following input String:
abc.def.ghi.jkl.mno
Number of dot characters may vary in the input. I want to extract the word after the last . (i.e. mno in the above example). I am using the following regex and its working perfectly fine:
String input = "abc.def.ghi.jkl.mno";
Pattern pattern = Pattern.compile("([^.]+$)");
Matcher matcher = pattern.matcher(input);
if(matcher.find()) {
System.out.println(matcher.group(1));
}
However, I am using a third party library which does this matching (Kafka Connect to be precise) and I can just provide the regex pattern to it. The issue is, this library (whose code I can't change) uses matches() instead of find() to do the matching, and when I execute the same code with matches(), it doesn't work e.g.:
String input = "abc.def.ghi.jkl.mno";
Pattern pattern = Pattern.compile("([^.]+$)");
Matcher matcher = pattern.matcher(input);
if(matcher.matches()) {
System.out.println(matcher.group(1));
}
The above code doesn't print anything. As per the javadoc, matches() tries to match the whole String. Is there any way I can apply similar logic using matches() to extract mno from my input String?
You may use
".*\\.([^.]*)"
It matches
.*\. - any 0+ chars as many as possible up to the last . char
([^.]*) - Capturing group 1: any 0+ chars other than a dot.
See the regex demo and the Regulex graph:
To extract a word after the last . per your instruction you could do this without Pattern and Matcher as following:
String input = "abc.def.ghi.jkl.mno";
String getMe = input.substring(input.lastIndexOf(".")+1, input.length());
System.out.println(getMe);
This will work. Use .* at the beginning to enable it to match the entire input.
public static void main(String[] argv) {
String input = "abc.def.ghi.jkl.mno";
Pattern pattern = Pattern.compile(".*([^.]{3})$");
Matcher matcher = pattern.matcher(input);
if(matcher.matches()) {
System.out.println(matcher.group(0));
System.out.println(matcher.group(1));
}
}
abc.def.ghi.jkl.mno
mno
This is a better pattern if the dot really is anywhere: ".*\\.([^.]+)$"

Regex to find a word between $$ sign

I want regular expression to find a word between $$ sign only. It must start and end with $ sign. I have tried below expression
final String regex = "\\$\\w+\\$";
final Pattern pattern = Pattern.compile(regex);
final Matcher matcher = pattern.matcher("$abc$ cde$efg$hij pqr");
This should give me count as 1. But my regular expression also considering second occurrence of (cde$efg$hij) which it should not consider as it is not starting and ending with $$ sign.
You may use non-word boundaries:
final String regex = "\\B\\$\\w+\\$\\B";
The pattern will only match if the $abc$ is not preceded and followed with word chars. See the regex demo.
See Java demo:
String regex = "\\B\\$\\w+\\$\\B";
Pattern pattern = Pattern.compile(regex);
Matcher matcher = pattern.matcher("$abc$ cde$efg$hij pqr");
while (matcher.find()){
System.out.println(matcher.group(0));
} // => $abc$
Besides non-word boundaries, you may use whitespace boundaries if you only want to match in between whitespace chars or start/end of string:
String regex = "(?<!\\S)\\$\\w+\\$(?!\\S)";
Or, use unambiguous word boundaries (as I call them):
String regex = "(?<!\\w)\\$\\w+\\$(?!\\w)";
The (?<!\\w) negative lookbehind will fail the match if a word char is found immediately to the left of the current location, and the (?!\w) negative lookahead will fail the match if a word char is found immediately to the right of the current location.
The problem was extracting fields between dollar signs for me.
List<String> getFieldNames(#NotNull String str) {
final String regex = "\\$(\\w+)\\$";
Pattern pattern = Pattern.compile(regex);
Matcher matcher = pattern.matcher(str);
List<String> fields = new ArrayList<>();
while (matcher.find()) {
fields.add(matcher.group(1));
}
return fields;
}
This will return list of words between dollar signs.

How do I build a regex to match these `long` values?

How do I build a regular expression for a long data type in Java, I currently have a regex expression for 3 double values as my pattern:
String pattern = "(max=[0-9]+\\.?[0-9]*) *(total=[0-9]+\\.?[0-9]*) *(free=[0-9]+\\.?[0-9]*)";
I am constructing the pattern using the line:
Pattern a = Pattern.compile("control.avgo:", Pattern.CASE_INSENSITIVE);
I want to match the numbers following the equals signs in the example text below, from the file control.avgo.
max=259522560, total=39325696, free=17979640
What do I need to do to correct my code to match them?
Could it be that you actually need
Pattern a = Pattern.compile(pattern, Pattern.CASE_INSENSITIVE);
instead of
Pattern a = Pattern.compile("control.avgo:", Pattern.CASE_INSENSITIVE);
because your current code uses "control.avgo:" as the regex, and not the pattern you have defined.
You need to address several errors, including:
Your pattern specifies real numbers, but your question asks for long integers.
Your pattern omits the commas in the string being searched.
The first argument to Pattern.compile() is the regular expression, not the string being searched.
This will work:
String sPattern = "max=([0-9]+), total=([0-9]+), free=([0-9]+)";
Pattern pattern = Pattern.compile( sPattern, Pattern.CASE_INSENSITIVE );
String source = "control.avgo: max=259522560, total=39325696, free=17979640";
Matcher matcher = pattern.matcher( source );
if ( matcher.find()) {
System.out.println("max=" + matcher.group(1));
System.out.println("total=" + matcher.group(2));
System.out.println("free=" + matcher.group(3));
}
If you want to convert the numbers you find to a numeric type, use Long.valueOf( String ).
In case you only need to find any numerical preceded by "="...
String test = "3.control.avgo: max=259522560, total=39325696, free=17979640";
// looks for the "=" sign preceding any numerical sequence of any length
Pattern pattern = Pattern.compile("(?<=\\=)\\d+");
Matcher matcher = pattern.matcher(test);
// keeps on searching until cannot find anymore
while (matcher.find()) {
// prints out whatever found
System.out.println(matcher.group());
}
Output:
259522560
39325696
17979640

RegEx performence issue

I have written a regular expression to validate a name. The name can start with alphabetics and can be followed by alphabetics, numbers, a space or a _.
The regex that I wrote is:
private static final String REGEX = "([a-zA-Z][a-zA-Z0-9 _]*)*";
If the input is: "kasklfhklasdhklghjsdkgsjkdbgjsbdjKg;" the program gets stuck on matcher.matches().
Pattern pattern = Pattern.compile(REGEX);
Matcher matcher = pattern.matcher(input);
if (matcher.matches()) {
System.out.println("Pattern Matches");
} else {
System.out.println("Match Declined");
}
How can I optimize the regex?
Change your regex to:
private static final String REGEX = "[a-zA-Z][a-zA-Z0-9 _]*";
And it will match the String in a click.

RegEX: how to match string which is not surrounded

I have a String "REC/LESS FEES/CODE/AU013423".
What could be the regEx expression to match "REC" and "AU013423" (anything that is not surrounded by slashes /)
I am using /^>*/, which works and matches the string within slash's i.e. using this I am able to find "/LESS FEES/CODE/", but I want to negate this to find reverse i.e. REC and AU013423.
Need help on this. Thanks
If you know that you're only looking for alphanumeric data you can use the regex ([A-Z0-9]+)/.*/([A-Z0-9]+) If this matches you will have the two groups which contain the first & final text strings.
This code prints RECAU013423
final String s = "REC/LESS FEES/CODE/AU013423";
final Pattern regex = Pattern.compile("([A-Z0-9]+)/.*/([A-Z0-9]+)", Pattern.CASE_INSENSITIVE);
final Matcher matcher = regex.matcher(s);
if (matcher.matches()) {
System.out.println(matcher.group(1) + matcher.group(2));
}
You can tweak the regex groups as necessary to cover valid characters
Here's another option:
String s = "REC/LESS FEES/CODE/AU013423";
String[] results = s.split("/.*/");
System.out.println(Arrays.toString(results));
// [REC, AU013423]
^[^/]+|[^/]+$
matches anything that occurs before the first or after the last slash in the string (or the entire string if there is no slash present).
To iterate over all matches in a string in Java:
Pattern regex = Pattern.compile("^[^/]+|[^/]+$");
Matcher regexMatcher = regex.matcher(subjectString);
while (regexMatcher.find()) {
// matched text: regexMatcher.group()
// match start: regexMatcher.start()
// match end: regexMatcher.end()
}

Categories