当前位置: 首页 > 面试题库 >

在Java正则表达式中获取组名

邹博明
2023-03-14
问题内容

我正在尝试同时接收模式和字符串,并返回组名的映射->匹配结果。

例:

(?<user>.*)

我想返回一个包含“ user”作为键及其匹配值的映射。

问题是我似乎无法从Java regex
api获取组名。我只能按名称或按索引获取匹配的值。我没有组名列表,Pattern和Matcher似乎都没有公开此信息。我检查了它的来源,似乎信息就在那里-
只是不向用户公开。

我尝试了Java的java.util.regex和jregex。(并且不必在乎是否有人建议其他任何支持该功能的,良好的,受支持的和高性能的库)。


问题答案:

Java中没有API来获取命名捕获组的名称。我认为这是一个缺少的功能。

一种简单的方法是从模式中选择候选的命名捕获组,然后尝试 从match中
访问命名组。换句话说,在插入匹配整个模式的字符串之前,您不知道命名捕获组的确切名称。

Pattern捕捉名为捕获组的名称是\(\?<([a-zA-Z][a-zA-Z0-9]*)>(根据派生Pattern类的文档)。

(最困难的方法是为正则表达式实现解析器并获取捕获组的名称)。

一个示例实现:

import java.util.Scanner;
import java.util.Set;
import java.util.TreeSet;
import java.util.Iterator;
import java.util.regex.Pattern;
import java.util.regex.Matcher;
import java.util.regex.MatchResult;

class RegexTester {

    public static void main(String args[]) {
        Scanner scanner = new Scanner(System.in);

        String regex = scanner.nextLine();
        StringBuilder input = new StringBuilder();
        while (scanner.hasNextLine()) {
            input.append(scanner.nextLine()).append('\n');
        }

        Set<String> namedGroups = getNamedGroupCandidates(regex);

        Pattern p = Pattern.compile(regex);
        Matcher m = p.matcher(input);
        int groupCount = m.groupCount();

        int matchCount = 0;

        if (m.find()) {
            // Remove invalid groups
            Iterator<String> i = namedGroups.iterator();
            while (i.hasNext()) {
                try {
                    m.group(i.next());
                } catch (IllegalArgumentException e) {
                    i.remove();
                }
            }

            matchCount += 1;
            System.out.println("Match " + matchCount + ":");
            System.out.println("=" + m.group() + "=");
            System.out.println();
            printMatches(m, namedGroups);

            while (m.find()) {
                matchCount += 1;
                System.out.println("Match " + matchCount + ":");
                System.out.println("=" + m.group() + "=");
                System.out.println();
                printMatches(m, namedGroups);
            }
        }
    }

    private static void printMatches(Matcher matcher, Set<String> namedGroups) {
        for (String name: namedGroups) {
            String matchedString = matcher.group(name);
            if (matchedString != null) {
                System.out.println(name + "=" + matchedString + "=");
            } else {
                System.out.println(name + "_");
            }
        }

        System.out.println();

        for (int i = 1; i < matcher.groupCount(); i++) {
            String matchedString = matcher.group(i);
            if (matchedString != null) {
                System.out.println(i + "=" + matchedString + "=");
            } else {
                System.out.println(i + "_");
            }
        }

        System.out.println();
    }

    private static Set<String> getNamedGroupCandidates(String regex) {
        Set<String> namedGroups = new TreeSet<String>();

        Matcher m = Pattern.compile("\\(\\?<([a-zA-Z][a-zA-Z0-9]*)>").matcher(regex);

            while (m.find()) {
                namedGroups.add(m.group(1));
            }

            return namedGroups;
        }
    }
}

但是,此实现有一个警告。目前,它不适用于regex
Pattern.COMMENTS模式。



 类似资料:
  • 问题内容: 我正在尝试使用Java expr在:之后捕获正确的部分,但是在以下代码中,打印的捕获组是整个字符串,怎么了? 问题答案: 子组的编号从1开始,全文为0。只需循环执行count + 1。

  • 问题内容: 给出以下Java表达式代码: 如果是,则表示正则表达式匹配整个“行”。那我可以得到两组的内容吗?每个是? 问题答案: 要访问组,您需要使用:。 然后,您可以调用或在匹配器上执行匹配器,如果匹配器返回true,则可以通过和访问组。

  • 假设我有这个虚拟URL,我需要提取植物及其颜色作为 下面的I have正在按预期捕获我需要的元素,但是当我的URL中的植物少于4株时,它无法捕获任何东西。底部有一个指向regex测试员的链接,其中有示例代码和URL,您可以使用。 如何修改这个正则表达式,使其动态工作,从而在不需要静态URL结构的情况下捕获可用内容。现在,假设我最多只能捕获4株植物(8组) https://regex101.com/

  • 问题内容: 我有以下一行, 我需要拿这个词ABC, 我写了以下代码片段, 所以,如果我说得到,ABC:但是如果我说是ABC,那么我想知道 这是什么和意味着什么呢?如果有人可以用很好的例子向我解释,那会更好。 正则表达式模式中包含一个:,为什么结果忽略了它?组1是否检测到括号内的所有单词? 因此,如果我再加上两个括号,例如:,那么会有两个小组吗?group(1)将退还零件并退还零件? 给出该代码段的

  • 问题内容: 据我了解,该软件包不支持命名组(http://www.regular-expressions.info/named.html),所以有人可以将我指向具有此名称的第三方库吗? 我看过jregex,但是它的最新版本是2002年,它在java5下对我不起作用(承认我只是短暂地尝试过)。 问题答案: 每个名称只能具有一个命名组(你并不总是可以控制!),并且不能将它们用于正则表达式内递归。 注意

  • 问题内容: 据我所知,JavaScript中没有所谓的捕获组。获得类似功能的替代方法是什么? 问题答案: ECMAScript 2018将命名捕获组引入了JavaScript正则表达式中。 例: 如果您需要支持较旧的浏览器,则可以使用命名捕获组来处理普通(编号)捕获组,而只需要跟踪编号-如果捕获组中的捕获组顺序很麻烦,正则表达式更改。 我能想到的命名捕获组只有两个“结构”优点: 在某些正则表达式中