一文秒懂java正则表达式命名捕获组示例及模版变量替换实战

Java正则命名捕获与模板替换

//matcher.appendReplacement方法含义解读
//从输入序列中读取字符,从追加位置开始,并将它们添加到给定的字符串缓冲区中。该方法在读取到前一个匹配之前的最后一个字符(即索引 start() - 1 处的字符)后停止。
//将给定的替换字符串添加到字符串缓冲区中。
//将此匹配器的追加位置设置为最后一个匹配字符的索引加一,即设置为 end()。
//替换字符串可以包含对前一次匹配期间捕获的子序列的引用:
//每个出现的 ${name} 或 $g 将分别被替换为计算相应 group(name) 或 group(g) 的结果
//对于 $g,$ 后的第一个数字始终被视为组引用的一部分。如果后续数字能形成合法的组引用,则它们会被纳入 g 中。
//只有数字 ‘0’ 到 ‘9’ 被视为组引用的潜在组成部分。
//例如,如果第二个组匹配字符串 “foo”,那么传递替换字符串 “$2bar” 将导致 “foobar” 被追加到字符串缓冲区中。
//要在替换字符串中包含字面意义的美元符号($),可以在其前面加上反斜线(\$)。
//请注意,替换字符串中的反斜线(\)和美元符号($)可能导致结果与将其视为字面替换字符串时不同。如上所述,美元符号可能被视为对捕获子序列的引用,而反斜线用于转义替换字符串中的字面字符。
}

package cn.richinfo.digital.util;

import java.util.HashMap;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * java正则表达式命名捕获组示例及模版变量替换实战
 */
public class NamedGroupExample {
    public static void main(String[] args) {
        useNameGroup();
        replaceTempalteVar();
    }

    /**
     * 使用命名捕获组
     */
    private static void useNameGroup() {
        String text = "姓名: 张三, 年龄: 25, 城市: 北京";

        // 使用命名捕获组 (?<name>pattern)  【jdk1.7 提供 】
        String regex = "姓名:\\s(?<name>\\S+),\\s年龄:\\s(?<age>\\d+),\\s城市:\\s(?<city>\\S+)";

        Pattern pattern = Pattern.compile(regex);
        Matcher matcher = pattern.matcher(text);

        if (matcher.find()) {
            System.out.println("使用命名组:");
            System.out.println("姓名: " + matcher.group("name"));
            System.out.println("年龄: " + matcher.group("age"));
            System.out.println("城市: " + matcher.group("city"));

            System.out.println("\n使用编号组:");
            System.out.println("组 1: " + matcher.group(1));
            System.out.println("组 2: " + matcher.group(2));
            System.out.println("组 3: " + matcher.group(3));
        }
    }

    /**
     * 命名捕获组的实际应用:替换模版变量
     */
    public static void replaceTempalteVar() {
        // 模拟从配置文件读取的模板
        StringBuffer configTemplate = new StringBuffer();
        configTemplate.append("server:");
            configTemplate.append("name: ${serverName}");
            configTemplate.append("port: ${serverPort}");
            configTemplate.append("environment: ${env}");
        configTemplate.append("database:");
            configTemplate.append("host: ${dbHost}");
            configTemplate.append("name: ${dbName}");


        // 模拟用户提供的配置值
        Map<String, String> configValues = new HashMap<>();
        configValues.put("serverName", "MyAppServer");
        configValues.put("serverPort", "8080");
        configValues.put("env", "production");
        configValues.put("dbHost", "localhost");
        configValues.put("dbName", "myapp_db");
        configValues.put("dbName", "${aaa}");

        // 匹配 ${key} 格式的占位符
        //使用命名捕获组 (?<name>pattern)
        String regex = "\\$\\{(?<key>\\w+)\\}";
        Pattern pattern = Pattern.compile(regex);
        Matcher matcher = pattern.matcher(configTemplate.toString());
        StringBuffer result = new StringBuffer();

        System.out.println("=== 模板渲染 ===");
        System.out.println("原始模板:");
        System.out.println(configTemplate);

        while (matcher.find()) {
            //命名捕获组匹配到值,等价于matcher.group(1); 在还没有命名捕获组时,捕获组就是用下标获取值
            String key = matcher.group("key");
            //String key = matcher.group(1);//等价
            String value = configValues.get(key);
            String replacement="";
            if (value != null) {
                // 注意:这里直接使用值替换,不是用占位符
                replacement=value;
                System.out.format("替换 ${%s} →%s%n" ,key, value);
            } else {
                // 如果找不到值,保留原占位符
                replacement=matcher.group();
            }
            //每个出现的 ${name} 或 $g 将分别被替换为计算相应 group(name) 或 group(g) 的结果
            //Matcher.quoteReplacement(replacement)
            // 转义美元符和反斜杠,防止map的value中出出现美元符如:${aaa},不转义会报错No group with name {aaa}
            matcher.appendReplacement(result, Matcher.quoteReplacement(replacement));
        }
        matcher.appendTail(result);

        System.out.println("\n渲染结果:");
        System.out.println(result.toString());
    }
    //matcher.appendReplacement方法含义解读
    //从输入序列中读取字符,从追加位置开始,并将它们添加到给定的字符串缓冲区中。该方法在读取到前一个匹配之前的最后一个字符(即索引 start() - 1 处的字符)后停止。
    //将给定的替换字符串添加到字符串缓冲区中。
    //将此匹配器的追加位置设置为最后一个匹配字符的索引加一,即设置为 end()。
    //替换字符串可以包含对前一次匹配期间捕获的子序列的引用:
    //每个出现的 ${name} 或 $g 将分别被替换为计算相应 group(name) 或 group(g) 的结果。
    //对于 $g,$ 后的第一个数字始终被视为组引用的一部分。如果后续数字能形成合法的组引用,则它们会被纳入 g 中。
    //只有数字 '0' 到 '9' 被视为组引用的潜在组成部分。
    //例如,如果第二个组匹配字符串 "foo",那么传递替换字符串 "$2bar" 将导致 "foobar" 被追加到字符串缓冲区中。
    //要在替换字符串中包含字面意义的美元符号($),可以在其前面加上反斜线(\$)。
    //请注意,替换字符串中的反斜线(\)和美元符号($)可能导致结果与将其视为字面替换字符串时不同。如上所述,美元符号可能被视为对捕获子序列的引用,而反斜线用于转义替换字符串中的字面字符。
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值