有没有办法在字符串上使用 replaceAll 但调用方法在每次匹配项出现时替换文本

Is there a way to use replaceAll on string but call method for replacing the text on each occurrence of a match

我想用不同的 UUID 替换所有出现的特定字符串。例如,

content = content.replaceAll("xyz", "xyz" + generateUUID());

但这里的问题是所有 "xyz" 都将被相同的 UUID 替换。但我希望每个 "xyz" 都被一个单独的唯一 ID 替换。如何做到这一点?

您可以使用 StringBuilder(为了提高效率,因为 String 是不可变的)、while 循环和类似

的东西
// content = content.replaceAll("xyz", "xyz" + generateUUID());
StringBuilder sb = new StringBuilder(content);
String toReplace = "xyz";
int toReplaceLen = toReplace.length();
int pos;
while ((pos = sb.indexOf(toReplace)) > -1) {
    sb.replace(pos, pos + toReplaceLen, generateUUID());
}
// content = sb.toString(); // <-- if you want to use content.

您可以使用 Matcher.appendReplacement 执行此操作。这将为您提供完整正则表达式的 replaceAll 功能(不仅仅是静态 String)。在这里,我使用 uidCounter 作为一个非常简单的 generateUUID;您应该能够根据您自己的 generateUUID 功能调整它。

public class AppendReplacementExample {
  public static void main(String[] args) throws Exception {
    int uidCounter = 1000;

    Pattern p = Pattern.compile("xyz");
    String test = "abc xyz def xyz ghi xyz";
    Matcher m = p.matcher(test);
    StringBuffer sb = new StringBuffer();

    while(m.find()) {
      m.appendReplacement(sb, m.group() + uidCounter);
      uidCounter++;
    }
    m.appendTail(sb);

    System.out.println(sb.toString());
  }
}

输出:

abc xyz1000 def xyz1001 ghi xyz1002

您似乎想要一种表达方式:

content = content.replaceAll("xyz", x -> x + generateUUID());

这里是 durron597 答案的改编版,几乎可以让您做到这一点:

content = replaceAll(content, "xyz", x -> x + generateUUID());

public static String replaceAll(String source, String regex, 
        Function<String, String> replacement) {
    StringBuffer sb = new StringBuffer();
    Pattern pattern = Pattern.compile(regex);
    Matcher matcher = pattern.matcher(source);
    while (matcher.find()) {
        matcher.appendReplacement(sb, replacement.apply(matcher.group(0)));
    }
    matcher.appendTail(sb);
    return sb.toString();
}