2015-06-21 181 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