Search code examples
javaregexreplacesplit

Placeholders wrongly replaced with % char


I want to change placeholder in a string, separated by % char. For example, %test% should be replaced by SERVER (in the example here). Others cases would be like %name% changed by the user name.

One of my problem is placeholders are not known before using it. So, we have to try for each placeholders to find if it's a valid one, or else keep the %.

Also, I can NOT know about the placeholders, and simply use a.replace("%test%", "SERVER"). I don't want to try to check if it's a right one because it could miss some, and/or have false positives.

Example of line:

abc %some%%test% efz %other% fref%

Some line with 1% of %some_placeholders%

My actual code:

public class Main {

    public static void main(String[] args) throws Exception {
        String base = "abc %some%%test% efz %other% fref%"; // here is my line

        String completeLine = ""; // the result
        String[] parts = base.split("\\%"); // split by separator
        for(int i = 0; i < parts.length; i++) { // for each parts
            String param = parts[i];
            String placeholder = placeholder(param); // change placeholder
            completeLine += placeholder;
            if(placeholder.equals(param) && i > 0) { // if not placeholder and not first %
                completeLine += "%";
            }
        }
        System.out.println(completeLine);
    }
    
    private static String placeholder(String param) {
        if(param.equalsIgnoreCase("test"))
            return "SERVER";
        return param;
    }
}

Actual result:

abc some%%SERVER efz %other% fref%

Expected result:

abc %some%SERVER efz %other% fref%

Before, I was using this:

public class Main {

    public static void main(String[] args) throws Exception {
        String base = "abc %some%%test% efz %other% fref%";

        String completeLine = "";
        for (String param : line.split("\\%")) {
            completeLine += placeholder(param);
        }
        System.out.println(completeLine);
    }
    
    private static String placeholder(String param) {
        if(param.equalsIgnoreCase("test"))
            return "SERVER";
        return param;
    }
}

But all % were disappearing, so the result was: abc someSERVER efz other fref.

I also think about checking char-by-char but it's too long and very non-efficient.

As you can see, the placeholder is well replaced but some % are missing. I tried to change when I add a new % (instead of adding after completeLine += placeholder;, I do it before). But I already don't have the right expected output (% are wrongly placed).

How can I keep the % without checking char-by-char?


Solution

  • You could also do the following:

    String base = "abc %some%%test% efz %other% fref%";
    Matcher m = Pattern.compile("%.*?%").matcher(base);
    String completeLine= base;
    while (m.find())  {
         completeLine = completeLine.replace(m.group(), placeholder(m.group()));
    }
    System.out.println(completeLine);
    
    private static Map<String,String> map = Map.of("%test%", "SERVER", "%other%", "OTHER");
    private static String placeholder(String param) {
        return map.getOrDefault(param, param);
    }
    

    prints

    abc %some%SERVER efz OTHER fref%
    

    The modification of the placeholder method is simply a suggestion on using a map to hold the placeholder to replacement mappings. If no mapping is found the original placeholder is returned.