循环通过RegEx匹配并替换当前匹配

时间:2017-04-21 07:38:04

标签: java regex

考虑以下字符串:

  他点了一份凤尾鱼披萨。不幸的是,这不是他想要的。此外,披萨配蘑菇,意大利辣香肠和凤尾鱼比普通披萨配凤尾鱼要好得多。

假设您需要将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.");
}

然后输出为:

  他在薄薄的外壳上点了一块披着凤尾鱼的薄饼。不幸的是,这不是他想要的。此外,配上蘑菇,意大利辣香肠和凤尾鱼的披萨比普通的披萨要好得多,而薄皮上的薄皮上有凤尾鱼。

发生了什么:

第一场比赛pizza with anchovies与上一场比赛相同。因此,使用String.replace会导致第一个和最后一个匹配更改为pizza with anchovies on a thin crust。因为,我们循环遍历所有匹配,最后的匹配仍将发生,并且替换函数也将替换第一个匹配(因为第一个匹配和最后一个匹配是相同的)。因此,我们得到双on a thin crust

问:

有没有办法在当前比赛中替换正则表达式匹配?

1 个答案:

答案 0 :(得分:6)

使用replaceAll使用$0反向引用整个匹配的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. 来执行此操作:

replaceAll()

请参阅Java demo

这样,您将避免替换已替换的文本,因为/admin/miscellaneous/whatsnew/add/?title=...%20competition%20results%20uploaded&pub_date=21-04-2017&body=&link= 处理符合您的正则表达式模式的子串的所有,多个,非重叠的出现。