24

我正在使用 awhile(matcher.find())来遍历 Pattern 的所有匹配项。对于它找到的该模式的每个实例或匹配,我想matcher.group(3)用一些新文本替换。每个文本都不同,因此我使用matcher.appendReplacement()新的更改重建原始字符串。但是,appendReplacement()替换整个 Pattern 而不仅仅是组。

我怎样才能做到这一点,但只修改匹配的第三组而不是整个模式?

这是一些示例代码:

Pattern pattern = Pattern.compile("THE (REGEX) (EXPRESSION) (WITH MULTIPLE) GROUPS");
Matcher matcher = pattern.matcher("THE TEXT TO SEARCH AND MODIFY");
StringBuffer buffer = new StringBuffer();

while(matcher.find()){
   matcher.appendReplacement(buffer, processTheGroup(matcher.group(3));
}

但我想做这样的事情(显然这不起作用)。

...
while(matcher.find()){
   matcher.group(3).appendReplacement(buffer, processTheGroup(matcher.group(3));
}

类似的东西,它只替换某个组,而不是整个 Pattern。

编辑:更改了正则表达式示例以显示并非所有模式都被分组。

4

2 回答 2

34

我看到这已经有一个公认的答案,但它并不完全正确。正确的答案似乎是这样的:

.appendReplacement("$1" + process(m.group(2)) + "$3");

这也说明了“$”是.appendReplacement 中的一个特殊字符。因此,您必须注意在“process()”函数中将所有“$”替换为“\$”。Matcher.quoteReplacement(replacementString) 将为您执行此操作(感谢@Med)

如果第 1 组或第 3 组碰巧包含“$”,则先前接受的答案将失败。你最终会得到“java.lang.IllegalArgumentException: Illegal group reference”

于 2011-03-24T12:50:18.180 回答
17

假设您的整个模式匹配"(prefix)(infix)(suffix)",将 3 个部分分别捕获到第 1、2 和 3 组。现在假设您只想替换第 2 组(中缀),保持前缀和后缀不变。

然后你要做的是附加group(1)匹配的(未更改的)、新的替换group(2)group(3)匹配的(未更改),如下所示:

matcher.appendReplacement(
    buffer,
    matcher.group(1) + processTheGroup(matcher.group(2)) + matcher.group(3)
);

这仍然会匹配并替换整个模式,但由于第 1 组和第 3 组保持不变,因此实际上只替换了中缀。

您应该能够为您的特定场景调整相同的基本技术。

于 2010-10-15T07:24:15.310 回答