Search code examples
javaregexstringhashmapbackreference

How to use backreference of a String-replacement as a key for a HashMap in Java?


I'd like to search for Strings that are enclosed by ${...} and use those Strings as keys for a HashMap, that contains the values I'd like to use for replacing the ${...}.

In the following example, the String Master_${field1}_${field2}_End should be transformed into Master_slave1_slave2_End:

package com.stackoverflow;

import java.util.HashMap;
import java.util.Map;

public class RegExReplace {

    public static void main(String[] args) {
//      String string  = "Master_${field1}_${field2}_${nonexisting}_End";
        String string  = "Master_${field1}_${field2}_End";
        Map<String, String> toBeInserted = new HashMap<String, String>();
        toBeInserted.put("field1", "slave1");
        toBeInserted.put("field2", "slave2");
        toBeInserted.put("field3", "slave3");

        String pattern = "\\$\\{([a-zA-Z0-9\\-_]*)\\}";
        String replace = "$1";

//      System.out.println(string.replaceAll(pattern, replace));
        System.out.println(string.replaceAll(pattern, toBeInserted.get(replace)));

    } // END: main()

} // END: class

(How) is it possible, to use the backreference as a key for the HashMap?


Solution

  • You can use iteration over the matches of your Pattern and a StringBuffer to append replacements, as such:

    String string  = "Master_${field1}_${field2}_End";
    Map<String, String> toBeInserted = new HashMap<String, String>();
    toBeInserted.put("field1", "slave1");
    toBeInserted.put("field2", "slave2");
    toBeInserted.put("field3", "slave3");
    
    Pattern p = Pattern.compile("\\$\\{(.+?)\\}");
    Matcher m = p.matcher(string);
    StringBuffer sb = new StringBuffer();
    while (m.find()) {
        String key = m.group(1);
        if (key != null) {
            String value =  toBeInserted.get(key);
            if (value != null)
                m.appendReplacement(sb, value);
        }
    }
    m.appendTail(sb);
    System.out.println(sb.toString());
    

    Output

    Master_slave1_slave2_End