Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Looping through RegEx matches and replace the current match

Tags:

java

regex

Consider the following string:

He ordered a pizza with anchovies. Unfortunately, it wasn't the thing he wanted. Besides, pizza with mushroom, pepperoni and anchovies is much better than the normal pizza with anchovies.

Let's say that you need to change pizza with (ingredients) to pizza with (ingredients) on a thin crust.

To do that, I had set a Regex:

(?i:pizza with [a-zA-Z,\s]*?anchovies)

This captures three matches. Then, I proceed to add the on a thin crust to each match using the following code:

Pattern p = Pattern.compile("(?i:pizza with [a-zA-Z,\s]*?anchovies)");
Matcher m = p.matcher(string);
while(m.find())
{
    string = string.replace(m.group(), m.group() + "on a thin crust.");
}

The output of this will then be:

He ordered a pizza with anchovies on a thin crust on a thin crust. Unfortunately, it wasn't the thing he wanted. Besides, pizza with mushroom, pepperoni and anchovies is much better than the normal pizza with anchovies on a thin crust on a thin crust.

What happened:

The first match pizza with anchovies is the same as the last match. Hence, using String.replace caused the first and last match to change to pizza with anchovies on a thin crust. Since, we are looping through all matches, the last match will still occur and the replace function will also replace the first match (since first match and last match are the same). Hence, we get double on a thin crust.

Q:

Is there a way to replace a Regex match at the current match only?

like image 826
Kawamoto Takeshi Avatar asked Apr 21 '17 07:04

Kawamoto Takeshi


People also ask

Can I use regex in replace?

The Regex. Replace(String, String, MatchEvaluator, RegexOptions) method is useful for replacing a regular expression match if any of the following conditions is true: If the replacement string cannot readily be specified by a regular expression replacement pattern.

How does Regex Replace work?

The REGEXREPLACE( ) function uses a regular expression to find matching patterns in data, and replaces any matching values with a new string. standardizes spacing in character data by replacing one or more spaces between text characters with a single space.

What is the difference between matches () and find () in Java regex?

Difference between matches() and find() in Java RegexThe matches() method returns true If the regular expression matches the whole text. If not, the matches() method returns false. Whereas find() search for the occurrence of the regular expression passes to Pattern.

How to use Regex in Replace c#?

Replace Special Characters from string using Regex in C# If you are having a string with special characters and want's to remove/replace them then you can use regex for that. Use this code: Regex. Replace(your String, @"[^0-9a-zA-Z]+", "")


1 Answers

Do it with a single replaceAll using $0 backreference to the whole match:

String s = "He ordered a pizza with anchovies. Unfortunately, it wasn't the thing he wanted. Besides, pizza with mushroom, pepperoni and anchovies is much better than the normal pizza with anchovies.";
s = s.replaceAll("(?i)pizza with [a-zA-Z,\\s]*?anchovies", "$0 on a thin crust");
System.out.println(s);
// => He ordered a pizza with anchovies on a thin crust. Unfortunately, it wasn't the thing 
//    he wanted. Besides, pizza with mushroom, pepperoni and anchovies on a thin crust is 
//    much better than the normal pizza with anchovies on a thin crust.

See the Java demo

This way, you will avoid replacing already replaced texts since replaceAll() process all, multiple, non-overlapping occurrences of the substrings meeting your regex pattern.

like image 185
Wiktor Stribiżew Avatar answered Nov 14 '22 10:11

Wiktor Stribiżew