用 Map 中的 RegEx 键替换所有出现的字符串

Posted

技术标签:

【中文标题】用 Map 中的 RegEx 键替换所有出现的字符串【英文标题】:Replacing all occurrences of a String with RegEx keys from a Map 【发布时间】:2017-05-17 23:47:09 【问题描述】:

我有如下字符串,

Account=type=object,id=type=integer, format=int64, enum=[ENABLED, DISABLED], token=type=string, AssetPlayerRequest=type=object, 属性=assetPlayer=description=资产播放器详情, $ref=#/definitions/AssetPlayer,ImageFile=type=object, properties=description=type=string, filePath=type=string, fileUri =$ref=#/definitions/URI

我想将 $ref=#/definitions/URI$ref=#/definitions/AssetPlayer 等 RegEx 模式替换为带有 URIAssetPlayer 等键的 Map 中可用的值,这些键是 RegEx 本身的一部分。

如何在 Java 8 中实现这一点?

【问题讨论】:

【参考方案1】:

部分改编自Matcher.replaceAll()

public static void main(String[] args) 
    Map<String, String> replacements = new HashMap<>();
    replacements.put("AssetPlayer", "replacement1");
    replacements.put("URI", "replacement2");
    
    String input = "Account=type=object,id=type=integer, format=int64, enum=[ENABLED, DISABLED], token=type=string, AssetPlayerRequest=type=object, properties=assetPlayer=description=The asset player details, $ref=#/definitions/AssetPlayer,ImageFile=type=object, properties=description=type=string, filePath=type=string, fileUri=$ref=#/definitions/URI";
    
    Matcher matcher = Pattern.compile("\\\\$ref=#\\/definitions\\/(.+?)\\").matcher(input);
    StringBuffer sb = new StringBuffer();
    if (matcher.find()) 
        do 
            String replacement = replacements.get(matcher.group(1));
            matcher.appendReplacement(sb, Matcher.quoteReplacement(replacement));
         while (matcher.find());
        matcher.appendTail(sb);
        System.out.println(sb.toString());
     else 
        System.out.println(input);
    

输出:

Account=type=object,id=type=integer, format=int64, enum=[ENABLED, DISABLED], token=type=string, AssetPlayerRequest=type=object, properties=assetPlayer=description=The asset player details, replacement1,ImageFile=type=object, properties=description=type=string, filePath=type=string, fileUri=replacement2

从 Java 9 开始,您可以使用新的函数 Matcher.replaceAll() 简化此操作:

String result = Pattern.compile("\\\\$ref=#\\/definitions\\/(.+?)\\")
        .matcher(input)
        .replaceAll(match -> Matcher.quoteReplacement(replacements.get(match.group(1))));
System.out.println(result);

【讨论】:

请注意,/ 在 Java 正则表达式中没有特殊含义,因此不需要转义。您可以在if 语句中拉出StringBuffer sb = new StringBuffer(); 行,因为它不是必需的,当没有匹配时。 Java 9 将允许StringBuilder 在这里。终于……【参考方案2】:

替换字符串中需要更多逻辑的东西的通用公式在Matcher#appendReplacement

public String bindTemplateVariables(String input) 
    Pattern p = Pattern.compile("\\\\$ref=#/definitions/(.*?)\\");
    Matcher m = p.matcher(input);
    StringBuffer sb = new StringBuffer();
    while (m.find()) 
        String replacement = map.get(m.group(1));
        m.appendReplacement(sb, replacement);
    
    m.appendTail(sb);
    return sb.toString();

【讨论】:

以上是关于用 Map 中的 RegEx 键替换所有出现的字符串的主要内容,如果未能解决你的问题,请参考以下文章

如何使用Java replaceAll(regex,replacement)方法替换字符串中的所有方括号[重复]

用powershell中的regex替换子字符串

用字典值替换字符串中的字典键

C#Regex使用匹配值替换

C# Regex 用 <p> 替换一些 HTML 序列,用 </p> 替换一些

替换 Python 中第一次出现的字符串