【问题标题】:Java Pattern print capturing groupsJava 模式打印捕获组
【发布时间】:2013-11-16 09:34:39
【问题描述】:
((\d{1,2})/(\d{1,2})/(\d{2,4}))

有没有办法使用Pattern 对象检索所有捕获组的列表。我调试了对象,它说的只是有多少组 (5)。

我需要检索以下捕获组的列表。

输出示例:

0 ((\d{1,2})/(\d{1,2})/(\d{2,4}))
1 (\d{2})/(\d{2})/(\d{4})
2 \d{2}
3 \d{2}
4 \d{4}

更新:

我不一定要问是否存在正则表达式,但这将是最有利的。到目前为止,我已经创建了一个仅匹配最内部组的基本解析器(我不检查大多数越界条件)。我想知道是否有办法引用已经访问过的括号。我可能必须实现一个树结构?

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

public class App {

    public final char S = '(';
    public final char E = ')';
    public final char X = '\\';

    String errorMessage = "Malformed expression: ";

    /**
     * Actual Output:
     *    Groups: [(//), (\d{1,2}), (\d{1,2}), (\d{2,4})]
     * Expected Output:
     *    Groups: [\\b((\\d{1,2})/(\\d{1,2})/(\\d{2,4}))\\b, ((\\d{1,2})/(\\d{1,2})/(\\d{2,4})), (\d{1,2}), (\d{1,2}), (\d{2,4})]
     */

    public App() {
        String expression = "\\b((\\d{1,2})/(\\d{1,2})/(\\d{2,4}))\\b";
        String output = "";

        if (isValidExpression(expression)) {
            List<String> groups = findGroups(expression);
            output = "Groups: " + groups;
        } else {
            output = errorMessage;
        }

        System.out.println(output);
    }

    public List<String> findGroups(String expression) {
        List<String> groups = new ArrayList<>();
        int[] pos;
        int start;
        int end;
        String sub;
        boolean done = false;

        while (expression.length() > 0 && !done) {
            pos = scanString(expression);
            start = pos[0];
            end = pos[1];

            if (start == -1 || end == -1) {
                done = true;
                continue;
            }

            sub = expression.substring(start, end);
            expression = splice(expression, start, end);
            groups.add(0, sub);
        }

        return groups;
    }

    public int[] scanString(String str) {
        int[] range = new int[] { -1, -1 };
        int min = 0;
        int max = str.length() - 1;
        int start = min;
        int end = max;
        char curr;

        while (start <= max) {
            curr = str.charAt(start);
            if (curr == S) {
                range[0] = start;
            }
            start++;
        }

        end = range[0];

        while (end > -1 && end <= max) {
            curr = str.charAt(end);
            if (curr == E) {
                range[1] = end + 1;
                break;
            }

            end++;
        }

        return range;
    }

    public String splice(String str, int start, int end) {
        if (str == null || str.length() < 1)
            return "";

        if (start < 0 || end > str.length()) {
            System.err.println("Positions out of bounds.");
            return str;
        }

        if (start >= end) {
            System.err.println("Start must not exceed end.");
            return str;
        }

        String first = str.substring(0, start);
        String last = str.substring(end, str.length());

        return first + last;
    }

    public boolean isValidExpression(String expression) {
        try {
            Pattern.compile(expression);
        } catch (PatternSyntaxException e) {
            errorMessage += e.getMessage();
            return false;
        }

        return true;
    }

    public static void main(String[] args) {
        new App();
    }
}

【问题讨论】:

  • 更好地解释你想用这个来完成什么 - 即它有什么用处。顺便说一句 - 那里有 3 个组而不是 5 个
  • 嗯...我在您的模式中只看到 4 个组。我出了什么问题
  • @Paul:好的,现在我知道你的意思了。我在他的正则表达式中计算组(等于 openinig 括号的数量),您将组计算为 Matcher 提供的结果数;-)
  • 如果没有人能弄清楚 OP 真正想要什么,谁对这个问题投了赞成票!!
  • @Paolo 类似,但没有好的答案。接受的答案声称子表达式不可用。这是真的,因为它没有内置方法,但这个问题是关于如何创建这样的方法。

标签: java regex capturing-group


【解决方案1】:

这是我的解决方案......我只是提供了一个正则表达式的正则表达式,正如 @SotiriosDelimanolis 注释掉的那样。

public static void printGroups() {
        String sp = "((\\(\\\\d\\{1,2\\}\\))\\/(\\(\\\\d\\{1,2\\}\\))\\/(\\(\\\\d\\{2,4\\}\\)))";
        Pattern p = Pattern.compile(sp);
        Matcher m = p.matcher("(\\d{1,2})/(\\d{1,2})/(\\d{2,4})");
        if (m.matches())
            for (int i = 0; i <= m.groupCount(); i++)
                System.out.println(m.group(i));
    }

注意你不能删除if-statement,因为要使用group方法你应该先调用matches方法(我不知道!)。请参阅 this link 作为有关它的参考。

希望这是你所要求的......

【讨论】:

  • 我感觉所使用的模式只是示例。您应该尝试找出更一般情况的方法,例如(group)\\(no group\\)and another [(]no group[)]
  • 是的,我想知道是否有更一般的情况。感谢您的意见。我在想我必须按组解析字符串。所以我会抓取pattern.substring(pattern.indexOf('('), pattern.indexOf(')'))的子串。在这个问题中,我不一定是在寻求正则表达式来解决我的问题,而是一种获取所有匹配组的方法。我将尝试编写我的方法并更新此问题或创建一个新问题。
猜你喜欢
  • 1970-01-01
  • 2021-02-24
  • 2021-03-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多