I'm trying to replace all occurrences of ${placeholders} with values from a lookup map of placeholder -> value
The code below doesn't quite cut it.
Expected :[foobar, foobar, foobar, afoobbarc]
Actual :[foobar, foobar, ${key1}bar, a${key1}bbarc]
Can anyone think of a better regex?
private static final Pattern replaceRegex = Pattern.compile(".*(\\$\\{?([^}] )}).*");
public static String resolvePlaceholder(Map<String, String> map, String s){
String returnValue = s;
for (Matcher m = replaceRegex.matcher(s); m.find(); ) {
if (map.containsKey(m.group(2))) {
returnValue = returnValue.replace(m.group(1), map.get(m.group(2)));
}
}
return returnValue;
}
@Test
public void test() {
// Given a map of a million entries
Map<String, String> veryBigMap = new HashMap<>();
veryBigMap.put("key1", "foo");
veryBigMap.put("key2", "bar");
// And test cases
Stream<String> testCases = Stream.of("${key1}bar", "foo${key2}", "${key1}${key2}", "a${key1}b${key2}c");
// When resolving placeholders
List<String> actual = testCases
.map(t -> resolvePlaceholder(veryBigMap, t))
.collect(Collectors.toList());
// Then placeholders get replaced
assertEquals(
Arrays.asList("foobar", "foobar", "foobar", "afoobbarc"),
actual);
}
Many thanks
Fil
CodePudding user response:
The following version, which uses a StringBuffer
to iteratively build the output string, should work:
private static final Pattern replaceRegex = Pattern.compile("\\$\\{(.*?)\\}");
public static String resolvePlaceholder(Map<String, String> map, String s) {
StringBuffer sb = new StringBuffer();
Matcher m = replaceRegex.matcher(s);
while (m.find()) {
m.appendReplacement(sb, map.get(m.group(1)));
}
m.appendTail(sb);
return sb.toString();
}