2015-06-21 175 views
1

我想用替換替換某些子字符串,兩者都在Hashmap中定義。一個例子是:替換字符串中的多個子字符串

import java.util.HashMap; 
import java.util.regex.Matcher; 
import java.util.regex.Pattern; 

public class RegexTest { 
    private static HashMap<String, String> conversionTable; 

    public static void main(String[] args) { 
     initConversionTable(); 
     System.out.println(convertNumbers("la1")); 
     System.out.println(convertNumbers("la1, lb3")); 
    } 

    private static String convertNumbers(String text) { 
     String regex = "([aub][1-3])"; 
     Matcher m = Pattern.compile(regex).matcher(text); 
     while(m.find()) { 
      text = m.replaceAll(conversionTable.get(m.group())); 
     } 

     return text; 
    } 

    private static void initConversionTable() { 
     conversionTable = new HashMap<>(); 
     conversionTable.put("a1", "A1"); 
     conversionTable.put("a2", "A2"); 
     conversionTable.put("a3", "A3"); 
     conversionTable.put("u1", "U1"); 
     conversionTable.put("u2", "U2"); 
     conversionTable.put("u3", "U3"); 
     conversionTable.put("b1", "B1"); 
     conversionTable.put("b2", "B2"); 
     conversionTable.put("b3", "B3"); 
    } 
} 

輸入數據

la1 
la1, lb3 

預期的結果應該是

lA1 
lA1, lB3 

lA1 
lA1, lA1 

到現在爲止我還沒有成功使用Match找到解決方案呃。有沒有這樣的解決方案?當然,我可以通過HashMap的每個條目並進行替換,但我想用匹配器來解決它,因爲我擔心對於很長的哈希表和許多字符串,這可能會影響性能。

非常感謝!

+0

正如接受的答案中所解釋的那樣,replaceAll替換了所有匹配正則表達式匹配的匹配項,它會在find()方法中阻止其他匹配項和正確的替換項。但要解決這個問題,不要使用'replaceFirst'。當我們想要與另一個動態確定的替換(如基於地圖中的鍵的值)匹配時,請使用適當的工具來處理這種場景。所以使用Matcher類中的'appendReplacement'和'appendTail'。 – Pshemo

+0

我把你的問題作爲問題的重複來解決,你可以在這裏看到使用這些方法的解決方案之一。你也可以看看http://stackoverflow.com/a/25081783/1393766,http://stackoverflow.com/a/23689796/1393766 – Pshemo

回答

1

問題是你使用replaceAll方法,所以會發生這種情況。

第1步:

la1 
la1, lb3 

將進入循環,因爲m.Find()返回true。它會找到第一個模式「la1」。現在您將從「lA1」表中轉換出來,並替換「la1」和「lb3」這兩個模式的所有出現。 然後循環不會再因爲輸出已經

lA1 
lA1, lA1 

要解決你需要替換隻有一個與coresponding值occurence問題迭代,否則就會與第一個替換他們。

+0

等其他例子謝謝你的解釋,問題現在已經清楚我。我已經用'text = text.replace(m.group(),conversionTable.get(m.group()));'替換了替換髮生的那一行。但爲什麼'text = m.replaceFirst(conversionTable.get(m.group()));'不工作,即空結果? – Rolch2015

+1

也許您需要重置循環的匹配器以再次正確評估:https://docs.oracle.com/javase/8/docs/api/java/util/regex/Matcher.html#replaceFirst-java.lang。字符串- – Kyborek

+0

我剛剛看到它,並嘗試過,但它沒有奏效。進一步閱讀應該可以解決這個問題,但我現在會堅持我的第一個解決方案,否則它會變得複雜。再次感謝你 :) – Rolch2015