Java正则表达式的查找和替换

4

当编写带有查找和替换功能的文本编辑器时,用户可以搜索多次然后进行替换。在Java中,搜索部分非常容易:

Pattern pattern = Pattern.compile(userInput);
...
String line = ...
Matcher matcher = pattern.matcher(line);
int from = 0;
while (from < line.length() && matcher.find(from)) {
  int start = matcher.start();
  int length = matcher.end() - start;
  // pseudo-code:
  if (askUser()) {
    return ...
  }

  from = start + 1;
}

但如何处理第n个匹配项的替换呢?Matcher有replaceAll和replaceFirst。显然,第一个方法不合适,而对于replaceFirst,文档中说:
“用给定的替换字符串替换输入序列中与模式匹配的第一个子序列。 此方法首先重置此匹配器。然后,它扫描输入序列,查找模式的匹配项。”
其中粗体句子让我担心它是否适用于这里。我需要一些东西来用特定的模式替换当前的匹配项。
2个回答

6

如果您想替换特定的匹配项,请多次调用find()并使用start()end()方法替换匹配部分。

StringBuilder builder = new StringBuilder(stringToMatch);
Matcher m = Pattern.compile(yourRegex).matcher(stringToMatch);
for (int i = 0 ; i < n ; i++) { // n is the nth match you want to replace
    m.find();
}
builder.replace(m.start(), m.end(), yourReplacement);

我猜,这个代码不会处理 yourReplacement 中的正则表达式语法,对吗? - Thomas S.
@ThomasS。好的,你可以通过执行 m.group(1) 来创建一个由匹配组成的替换字符串,比如 \1 很类似。 - Sweeper

1
如果您想使用完整的Matcher.replaceFirst语法替换,其中可能包含对捕获组的引用,您可以查看replaceFirst的源代码。它调用Matcher中的两个公共方法:appendReplacement和appendTail。您也可以在不重置匹配器和不执行find调用的情况下直接调用它们:
StringBuffer sb = new StringBuffer();
matcher.appendReplacement(sb, replacement);
matcher.appendTail(sb);

这将生成一个新的StringBuffer,其中输入字符串除了当前匹配项被替换为您的替换字符串(可以包含对捕获组的引用)。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接