在 replaceAll 中以编程方式获取捕获组

Posted

技术标签:

【中文标题】在 replaceAll 中以编程方式获取捕获组【英文标题】:Getting capturing group programatically in replaceAll 【发布时间】:2017-06-23 07:39:08 【问题描述】:

我想用解析的$1 替换字符串中每个出现的正则表达式。我该怎么做?

    String line = "foo <<VAR>> bar <<VAR>>";
    Matcher matcher = Pattern.compile("<<(\\w*?)>>").matcher(line);
    Map<String,String> replacements = Collections.singletonMap("VAR","REPLACEMENT");
    String replacedLine = matcher.replaceAll(replacements.get(?.group(1)));
    Assert.assertTrue("foo REPLACEMENT bar REPLACEMENT".equals(replacedLine));

【问题讨论】:

为什么不直接使用String的replaceAll方法? 【参考方案1】:

您可以使用Matcher#appendReplacement 方法来构建“匹配时”的结果:

String line = "foo <<VAR>> bar <<VAR>> in <<NO>>";
Matcher m = Pattern.compile("<<(\\w+)>>").matcher(line);
Map<String,String> replacements = Collections.singletonMap("VAR","REPLACEMENT");
StringBuffer replacedLine = new StringBuffer();
while (m.find()) 
    if (replacements.get(m.group(1)) != null)
        m.appendReplacement(replacedLine, replacements.get(m.group(1)));
    else
        m.appendReplacement(replacedLine, m.group());

m.appendTail(replacedLine);
System.out.println(replacedLine.toString()); // => foo REPLACEMENT bar REPLACEMENT in <<NO>>

请参阅Java demo。

【讨论】:

【参考方案2】:

这是否满足您的需求?

String line = "foo <<VAR>> bar <<VAR>>";

Map<String, String> replaceMap = new HashMap<>();
replaceMap.put("<<VAR>>", "REPLACEMENT");
//may be more replacement here

for(Map.Entry<String, String> entry: replaceMap.entrySet())
    line = line.replaceAll(entry.getKey(), entry.getValue());


System.out.println(line); //<- foo REPLACEMENT bar REPLACEMENT

【讨论】:

这很好,但我放弃了它,因为你必须在所有行上迭代每个映射值,这在大文件中似乎效率很低 @Whimusical 现在我明白了,但如果所有替换都确定,line.replaceAll() 可以替换为 line.replace(),我认为应该更快,但我仍然不知道会不会比获取所有正则表达式匹配更有效,因为我不知道正则表达式匹配的效率如何。

以上是关于在 replaceAll 中以编程方式获取捕获组的主要内容,如果未能解决你的问题,请参考以下文章

在目标 c 中以编程方式获取视频的尺寸

提高android应用程序中以编程方式捕获的图像的质量[重复]

在 c++ 中以可变帧速率使用 FFmpeg 库(不是 libav 分支)以编程方式捕获视频

是否可以在浏览器中以编程方式捕获页面上的所有事件?

在 liferay 中以编程方式创建站点(组)

如何在 Swift 中以编程方式旋转一组按钮?