Java正则表达式提取并替换为值

Java正则表达式提取并替换为值,java,regex,regex-group,Java,Regex,Regex Group,输入字符串 ${abc.xzy}/demo/${ttt.bbb} test${kkk.mmm} 结果 世界/演示/你好 测试系统 花括号内的文本是“我的属性”的键。我想用运行时值替换这些属性 我可以执行以下操作来获得regex匹配,但是我应该在replace逻辑中添加什么来更改与输入字符串中相应的运行时值匹配的${..} Pattern p = Pattern.compile("\\{([^}]*)\\}"); Matcher m = p.matcher(s); while (m.find()

输入字符串

${abc.xzy}/demo/${ttt.bbb}
test${kkk.mmm}
结果 世界/演示/你好 测试系统

花括号内的文本是“我的属性”的键。我想用运行时值替换这些属性

我可以执行以下操作来获得regex匹配,但是我应该在replace逻辑中添加什么来更改与输入字符串中相应的运行时值匹配的${..}

Pattern p = Pattern.compile("\\{([^}]*)\\}");
Matcher m = p.matcher(s);
while (m.find()) {
  // replace logic comes here
}

你的正则表达式需要包含美元。另外,使内部组变为惰性就足以在生成的键字符串中不包含任何
}

String regex=“\\$\{(+.+?)\\}”;
Pattern p=Pattern.compile(regex);
匹配器m=匹配器p;
while(m.find()){
String key=m.group(1);//这是匹配的组(大括号中的组)。
字符串值=someMap.get(键);
s、 replaceFirst(regex,value!=null?值:“missingKey”);
m=p.matcher(s);//为了简单起见,您也可以重置现有的匹配器,但只需创建一个新的匹配器即可。
}

您可以通过提取光标位置并自己替换字符串来简化此过程。但无论哪种方式,您都需要重置匹配器,否则它将解析旧字符串。

您可以使用以下解决方案:

String s = "${abc.xzy}/demo/${ttt.bbb}\ntest${kkk.mmm}";
Map<String, String> map = new HashMap<String, String>();
map.put("abc.xzy", "World");
map.put("ttt.bbb", "Hello");
map.put("kkk.mmm", "System");
StringBuffer result = new StringBuffer();
Matcher m = Pattern.compile("\\$\\{([^{}]+)\\}").matcher(s);
while (m.find()) {
    String value = map.get(m.group(1));
    m.appendReplacement(result, value != null ? value : m.group());
}
m.appendTail(result);
System.out.println(result.toString());
正则表达式是

\$\{([^{}]+)\}

看。它匹配
${
字符串,然后将
{
}
以外的任何1+字符捕获到组1中,然后匹配
}
。如果组1值作为键出现在映射中,则替换为键值,否则,匹配的文本将粘贴回输入字符串中的位置。

另一种方法可能是使用第三方库,如Apache Commons text。
Pattern p = Pattern.compile("\\{([^}]*)\\}");
Matcher m = p.matcher(s);
while (m.find()) {
  // replace logic comes here
}
他们的替补课看起来很有前途

Map valuesMap = HashMap();
valuesMap.put("abc.xzy", "World");
valuesMap.put("ttt.bbb", "Hello");
valuesMap.put("kkk.mmm", "System");

String templateString = "${abc.xzy}/demo/${ttt.bbb} test${kkk.mmm}"
StringSubstitutor sub = new StringSubstitutor(valuesMap);
String resolvedString = sub.replace(templateString);

要了解更多信息,请查看Javadoc。可爱刺猬的答案很好,但包含一个依赖项。
维克托·斯特里比奥的答案遗漏了一个特例

我的答案旨在在正则表达式中使用java构建,并尝试从Wiktor Stribiżew的答案中改进。(仅在Java代码中改进,正则表达式还可以)

改进:

  • 使用
    StringBuilder
    StringBuffer
  • 初始
    StringBuilder
    能够
    (int)(s.length()*1.2)
    ,避免在输入模板
    s
    较大时多次重新定位内存
  • 避免正则表达式特殊字符通过
    appendReplacement
    (如
    “cost:$100”
    )产生错误结果的情况。您可以在Wiktor Stribiżew的代码中通过替换字符串中的转义
    $
    字符解决此问题,如
    value.replaceAll(“\\$”,“\\$”)
以下是改进后的代码:

String s=“khj${abc.xzy}/demo/${ttt.bbb}\ntest${kkk.mmm}{kkk.missing}String”;
Map Map=newhashmap();
地图放置(“abc.xzy”,“世界”);
地图出售(“ttt.bbb”,“成本:$100”);
地图放置(“kkk.mmm”,“系统”);
StringBuilder结果=新的StringBuilder((int)(s.length()*1.2));
Matcher m=Pattern.compile(“\\$\\{([^}]+)\}”).Matcher(s);
int nonCaptureIndex=0;
while(m.find()){
字符串值=map.get(m.group(1));
if(值!=null){
int index=m.start();
如果(索引>非捕获索引){
追加(s.substring(nonCaptureIndex,index));
}
结果。追加(值);
非捕获索引=m.end();
}
}
追加(s.substring(nonCaptureIndex,s.length());
System.out.println(result.toString());

检查,可能就足够了。这比我的解决方案好。我不知道有什么事。相当整洁的特点。