2017-04-21 69 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()過程中的所有,多個非取代已經取代文本 - 重疊符合您的正則表達式模式的子字符串的出現次數。