考虑以下字符串:
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.
假设您需要将 pizza with (ingredients)
更改为 pizza with (ingredients) on a thin crust
。
为此,我设置了一个正则表达式:
(?i:pizza with [a-zA-Z,\s]*?anchovies)
这会捕获三个匹配项。然后,我继续使用以下代码将 on a thin crust
添加到每个匹配项:
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.");
}
这样的输出将是:
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.
发生了什么:
第一场比赛 pizza with anchovies
与最后一场比赛相同。因此,使用 String.replace
会导致第一个和最后一个匹配项更改为 pizza with anchovies on a thin crust
。因为,我们正在遍历所有匹配项,所以最后一个匹配项仍然会出现,替换函数也将替换第一个匹配项(因为第一个匹配项和最后一个匹配项是相同的)。因此,我们得到了双倍的薄壳
。
问:
有没有办法只在当前匹配中替换正则表达式匹配?
最佳答案
通过使用 $0
对整个匹配项的反向引用,通过单个 replaceAll
完成此操作:
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.
参见 Java demo
这样一来,您将避免替换已经替换的文本,因为 replaceAll()
会处理满足您的正则表达式模式的所有、多个、非重叠的子字符串。
关于java - 循环遍历 RegEx 匹配并替换当前匹配,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43536696/