如何在匹配器组而不是整个模式上追加替换?

Posted

技术标签:

【中文标题】如何在匹配器组而不是整个模式上追加替换?【英文标题】:How to appendReplacement on a Matcher group instead of the whole pattern? 【发布时间】:2011-04-25 19:23:22 【问题描述】:

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

我怎样才能做到这一点,但只修改匹配的第三组而不是整个 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。

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

【问题讨论】:

【参考方案1】:

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

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

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

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

【讨论】:

要解决这个$ 问题,Matcher.quoteReplacement( replacementString ) 做得很好。【参考方案2】:

假设您的整个模式匹配 "(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 保持不变,实际上只替换了中缀。

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

【讨论】:

非常感谢。如果模式的某些方面不在组中,是否还有办法做到这一点? (我编辑了我原来的帖子的例子) 如果您必须在匹配中包含这些部分(即您不能将它们排除在模式之外),那么您需要将它们捕获在一个组中,这样您就可以记住它们匹配的内容并作为替换的一部分,将它们原封不动地放回去。 请注意,如果匹配的字符串之一包含$,这将失败。请参阅下面的沃伦斯回答。 好的,processTheGroup() 是什么?我想替换让我们说只有第 2 组

以上是关于如何在匹配器组而不是整个模式上追加替换?的主要内容,如果未能解决你的问题,请参考以下文章

sed 中如何替换换行符

如何确保 replaceAll 将替换整个单词而不是子字符串

使用 sed 在第 N 个匹配模式之后插入一些文本

如何实现潜在狄利克雷分配以在主题中给出二元组/三元组而不是一元组

如何替换 Javascript 中的正则表达式子字符串匹配?

如何使用与号 (&) 替换匹配模式中的字符