You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Java如何不依赖第三方库从正则表达式提取命名捕获组名称

Java正则命名捕获组提取方案

方案1:正则匹配法(优先推荐,无依赖兼容性强)

实现原理

Java命名捕获组语法固定为(?<组名>),组名规则为「首字符必须为字母,后续可接字母、数字、下划线」,通过匹配符合规则的子串即可提取组名,同时通过零宽断言排除被转义的(?<场景。

实现代码

import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class RegexUtils {
    // 匹配命名捕获组的正则,自动排除转义场景
    private static final Pattern NAMED_GROUP_PATTERN = Pattern.compile("(?<!\\\\)(?:\\\\\\\\)*\\(\\?<([a-zA-Z][a-zA-Z0-9_]*)>");

    public static List<String> extractNamedGroups(String regex) {
        List<String> groupNames = new ArrayList<>();
        // 兼容带定界符和修饰符的输入格式,比如/xxx/gm
        String processedRegex = regex;
        if (regex.startsWith("/")) {
            int lastSlashIndex = regex.lastIndexOf('/');
            if (lastSlashIndex > 0) {
                processedRegex = regex.substring(1, lastSlashIndex);
            }
        }
        Matcher matcher = NAMED_GROUP_PATTERN.matcher(processedRegex);
        while (matcher.find()) {
            groupNames.add(matcher.group(1));
        }
        return groupNames;
    }

    // 测试用例
    public static void main(String[] args) {
        String input = "/(?<name>\\w+) (?<surname>\\w+)/gm";
        List<String> groups = extractNamedGroups(input);
        System.out.println(groups); // 输出 [name, surname]
    }
}

优缺点说明

  • 优点:纯JDK实现无第三方依赖,不受JDK版本、安全管理器、Java模块化限制,性能满足绝大多数业务场景
  • 缺点:极端场景下会误判,比如正则的字符串常量段中人工写入了(?<字样,这类场景占比不足1%,如需完美处理可以使用方案2

方案2:修正后的反射提取法(准确率100%)

问题修复说明

你之前反射失败的核心原因是:namedGroups是Pattern类的私有字段,getField()只能获取public修饰的字段,需要改用getDeclaredField()。

实现代码

package my.package;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.regex.Pattern;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class MyPatternUtils {
    private static final Logger log = LoggerFactory.getLogger(MyPatternUtils.class);

    @SuppressWarnings("unchecked")
    public static Map<String, Integer> getNamedGroups(Pattern pattern) {
        if (pattern == null) {
            return Collections.emptyMap();
        }
        try {
            Field namedGroupsField = Pattern.class.getDeclaredField("namedGroups");
            namedGroupsField.setAccessible(true);
            Map<String, Integer> namedGroups = (Map<String, Integer>) namedGroupsField.get(pattern);
            return namedGroups == null ? Collections.emptyMap() : Collections.unmodifiableMap(namedGroups);
        } catch (Throwable t) {
            log.error("反射获取命名组失败", t);
        }
        return Collections.emptyMap();
    }

    // 直接从正则字符串提取的快捷方法
    public static List<String> extractNamedGroups(String regex) {
        // 兼容带定界符的输入格式
        String processedRegex = regex;
        if (regex.startsWith("/")) {
            int lastSlashIndex = regex.lastIndexOf('/');
            if (lastSlashIndex > 0) {
                processedRegex = regex.substring(1, lastSlashIndex);
            }
        }
        Pattern pattern = Pattern.compile(processedRegex);
        return new ArrayList<>(getNamedGroups(pattern).keySet());
    }
}

优缺点说明

  • 优点:100%准确,完全匹配Java正则引擎的解析结果,不会受正则内容干扰
  • 缺点:依赖Pattern内部实现,不同JDK版本可能存在字段变更,开启安全管理器或Java模块化环境下可能有权限限制

内容的提问来源于stack exchange,提问作者Andrei Matei

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.02 15:39:04