如何在 Matcher 组而不是整个模式上附加替换?

2022-09-01 20:16:46

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

我怎么能做到这一点,但只修改比赛的第三组,而不是整个模式?

下面是一些示例代码:

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));
}

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

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


答案 1

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

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

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

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


答案 2

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

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

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

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

您应该能够针对您的特定方案调整相同的基本技术。