当替换文本与搜索文本重叠时,用Java替换多个子字符串

Dav*_*les 6 java string replace

假设您有以下字符串:

cat dog fish dog fish cat
Run Code Online (Sandbox Code Playgroud)

要替换所有catsdogs,都dogs具有fish,和所有fishcats.直观地说,预期结果:

dog fish cat fish cat dog
Run Code Online (Sandbox Code Playgroud)

如果您尝试使用明显的解决方案,循环使用replaceAll(),您会得到:

  1. (原版的) cat dog fish dog fish cat
  2. (猫 - >狗) dog dog fish dog fish dog
  3. (狗 - >鱼) fish fish fish fish fish fish
  4. (鱼 - >猫) cat cat cat cat cat cat

显然,这不是预期的结果.那么最简单的方法是什么?我可以PatternMatcher(以及很多Pattern.quote()Matcher.quoteReplacement())一起拼凑一些东西,但我拒绝相信我是第一个遇到这个问题的人,并且没有库函数来解决它.

(FWIW,实际案例有点复杂,不涉及直接交换.)

Mis*_*ble 8

似乎在apache commons中的StringUtils.replaceEach做了你想要的:

StringUtils.replaceEach("abcdeab", new String[]{"ab", "cd"}, new String[]{"cd", "ab"});
// returns "cdabecd"
Run Code Online (Sandbox Code Playgroud)

请注意,上述链接中的文档似乎有误.请参阅以下评论了解详情.


Sea*_*oyd 7

String rep = str.replace("cat","§1§").replace("dog","§2§")
                .replace("fish","§3§").replace("§1§","dog")
                .replace("§2§","fish").replace("§3§","cat");
Run Code Online (Sandbox Code Playgroud)

像地狱一样丑陋和低效,但有效.


好的,这是一个更复杂和通用的版本.我更喜欢使用正则表达式而不是扫描仪.这样我就可以替换任意字符串,而不仅仅是单词(可以更好或更差).无论如何,这里是:

public static String replace(
    final String input, final Map<String, String> replacements) {

    if (input == null || "".equals(input) || replacements == null 
        || replacements.isEmpty()) {
        return input;
    }
    StringBuilder regexBuilder = new StringBuilder();
    Iterator<String> 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();
}
Run Code Online (Sandbox Code Playgroud)

测试代码:

System.out.println(replace("cat dog fish dog fish cat",
    ImmutableMap.of("cat", "dog", "dog", "fish", "fish", "cat")));
Run Code Online (Sandbox Code Playgroud)

输出:

狗鱼猫鱼猫狗

显然这个解决方案只对许多替代品有意义,否则这是一个巨大的矫枉过正.