Replacing multiple substrings in Java when replacement text overlaps search text

前端 未结 5 707
囚心锁ツ
囚心锁ツ 2021-01-12 20:54

Say you have the following string:

cat dog fish dog fish cat

You want to replace all cats with dogs, all do

5条回答
  •  轻奢々
    轻奢々 (楼主)
    2021-01-12 21:42

    String rep = str.replace("cat","§1§").replace("dog","§2§")
                    .replace("fish","§3§").replace("§1§","dog")
                    .replace("§2§","fish").replace("§3§","cat");
    

    Ugly and inefficient as hell, but works.


    OK, here's a more elaborate and generic version. I prefer using a regular expression rather than a scanner. That way I can replace arbitrary Strings, not just words (which can be better or worse). Anyway, here goes:

    public static String replace(
        final String input, final Map replacements) {
    
        if (input == null || "".equals(input) || replacements == null 
            || replacements.isEmpty()) {
            return input;
        }
        StringBuilder regexBuilder = new StringBuilder();
        Iterator it = replacements.keySet().iterator();
        regexBuilder.append(Pattern.quote(it.next()));
        while (it.hasNext()) {
            regexBuilder.append('|').append(Pattern.quote(it.next()));
        }
        Matcher matcher = Pattern.compile(regexBuilder.toString()).matcher(input);
        StringBuffer out = new StringBuffer(input.length() + (input.length() / 10));
        while (matcher.find()) {
            matcher.appendReplacement(out, replacements.get(matcher.group()));
        }
        matcher.appendTail(out);
        return out.toString();
    }
    

    Test Code:

    System.out.println(replace("cat dog fish dog fish cat",
        ImmutableMap.of("cat", "dog", "dog", "fish", "fish", "cat")));
    

    Output:

    dog fish cat fish cat dog

    Obviously this solution only makes sense for many replacements, otherwise it's a huge overkill.

提交回复
热议问题