【问题标题】:Java matcher how to dynamically replace groups based on their valueJava匹配器如何根据组的值动态替换组
【发布时间】:2018-05-13 23:01:56
【问题描述】:

对于一个快速示例,我有以下字符串:

String s = "hey.there.man.${a.a}crazy$carl${a.b}jones

我也有以下方法:

private String resolveMatchedValue(String s) {
    if(s.equals("a.a")) {
           return "A";
    else if(s.equals("a.b")) { 
           return "Wallet";
    else if(.....
    ....
 }

我的模式是

 Pattern pattern = Pattern.compile("\\$\\{(.*?)\\}");

因此,对于 s 中与 ${.*} 匹配的每个子字符串,我希望调用 resolveMatchedValue 方法,并且应该将其替换为该方法。所以理想情况下,正则表达式过程 s 应该是

 s = "hey.there.man.Acrazy$carl$Walletjones

我查看了类似的解决方案,但没有根据匹配值动态替换匹配值,并且无法使其工作

编辑:使用 java8

【问题讨论】:

  • 根据代码,输出不应该是"hey.there.man.Acrazy$carlWalletjones"吗?

标签: java regex java-8 matcher


【解决方案1】:

为了捕获正确的字符,您应该从您的组[^}]+ 中排除右花括号。事实上,最好只包含您正在寻找的特定模式以尽早发现错误:

Pattern pattern = Pattern.compile("\\$\\{([a-z]\\.[a-z]+)\\}");

Matcher.replaceAll​(Function<MatchResult,String> replacer) 方法旨在完全按照您的要求进行操作。传递给该方法的函数在每次匹配时都会获得并返回一个字符串来替换它。

在你的情况下:

pattern.matcher(input).replaceAll(mr -> resolveMatchedValue(mr.group(1)));

将返回一个字符串,其中所有与您的模式匹配的子字符串都被替换。

这是一个仅将字段大写的工作示例:

System.out.println(Pattern.compile("\\$\\{([[a-z]\\.[a-z])\\}")
    .matcher("hey.there.man.${a.a}crazy$carl${a.b}jones")
    .replaceAll(mr -> mr.group(1).toUpperCase()));

在 Java 9 之前的等价物是:

StringBuffer result = new StringBuffer();
while (matcher.find()) {
    matcher.appendReplacement(result, resolvedMatchedValue(matcher.group(1)));
}
matcher.appendTail(result);

之后result.toString() 保存新字符串。

【讨论】:

  • 谢谢你,不幸的是我被锁定到java 8
  • @yoplayone 这在您的原始问题中会很有用。我将提供 9 之前的替代方案。
猜你喜欢
  • 1970-01-01
  • 2012-03-01
  • 2019-01-27
  • 1970-01-01
  • 1970-01-01
  • 2021-07-17
  • 1970-01-01
  • 1970-01-01
  • 2020-09-29
相关资源
最近更新 更多