2017-04-21 41 views
6

考虑以下字符串:通过正则表达式匹配循环和替换当前匹配

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

比方说,您需要将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

问:

有没有一种方法来替代仅在当前匹配一个正则表达式匹配?

+0

如果您发现我的答案对您有帮助/为您工作,请考虑upvoting /接受。 –

回答

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. 

Java demo

这样一来,你会避免因为replaceAll()过程中的所有,多个非取代已经取代文本 - 重叠符合您的正则表达式模式的子字符串的出现次数。