Java-Regex,嵌套递归匹配

Java-Regex,嵌套递归匹配,java,regex,Java,Regex,我试图创建一个正则表达式模式来匹配每个(content*),但是可以在另一个((content)(content))中找到该模式。 我尝试了“\(*?)”,但这会返回外部的 例如:字符串('fdmg')(R:Percentual('dmg')(20))应返回: 匹配一个:fdmg 匹配二:R:Percentual('dmg')(20) 编辑: 我试过:\((?:[0-9A-Z-a-Z':]|(?R))*\) 但是我在?R(unknow flag)附近得到了一个错误如果您只需要2级嵌套,如问题中所

我试图创建一个正则表达式模式来匹配每个(content*),但是可以在另一个((content)(content))中找到该模式。 我尝试了
“\(*?)”
,但这会返回外部的

例如:字符串
('fdmg')(R:Percentual('dmg')(20))
应返回:

匹配一个:
fdmg

匹配二:
R:Percentual('dmg')(20)

编辑:

我试过:
\((?:[0-9A-Z-a-Z':]|(?R))*\)

但是我在?R(unknow flag)附近得到了一个错误

如果您只需要2级嵌套,如问题中所示,但不需要更深层的递归,那么您可以使用正向的lookaheads来完成

正则表达式:
(?=(\([^()]*(?:\([^()]*\)[^()]*)*))

请参见演示

结果(第1组*)

('fdmg')
(R:百分比(‘dmg’)(20))
(‘dmg’)
(20)

*)组0始终是一个空字符串。

我知道这是一个与正则表达式相关的问题,但我想我会把它放在这里

就我个人而言,我不会尝试正则表达式获取特定的嵌套括号深度,即使您尝试获取的深度仅为1。以下是两种方法,可以在括号类型的任何深度检索所需的括号子字符串:
()
[]
{}
,以及


如果我没有记错我的CS课程,那么在一般情况下,纯正则表达式就不能正确地做到这一点,因为它需要计算开始括号和结束括号。如果有最大嵌套深度,那么你可以编写一个难看但可行的正则表达式来实现这一点。也许一些正则表达式引擎具有支持这一点的功能(这将超越“正则表达式”的严格定义。)天哪……这太棒了,tysm!
/**
 * This method will parse out (retrieve) the contents of nested brackets
 * groups within a bracketed string and return those group contents within a
 * Single Dimensional String Array. The best way to see how this works is by 
 * examples. Let's say we have the following bracketed string:<pre>
 *
 *      String a = "1(2(3)(4))(5(6)(7))";</pre><br>
 *
 * In the above string we can see that there are two instances of level 1
 * bracketed groups which in each level 1 group nest two more level 2
 * bracketed groups:
 * <pre>
 *
 *       Level 1         Level 2
 *      (2(3)(4))        (3) (4)
 *
 * ==================================
 *
 *       Level 1         Level 2
 *       (5(6)(7))       (6) (7)</pre><br>
 * 
 * Bracketed groups: <b>(2(3)(4))</b> and <b>(5(6)(7))</b> are both
 * considered to be at nest level 1 (level 1 is the outer most level). They
 * are both individual groups because they both have their own set of outer
 * brackets. Within each level 1 group we have two sets of level 2 bracketed
 * groups (4 level 2 groups altogether) which consist of: <b>(3)</b> &
 * <b>(4)</b> and <b>(6)</b> & <b>
 * (7)</b>.<br><br>
 * 
 * This method also utilizes the bracketsMaxDepth() method.
 *
 * @param bracketedString     (String) The string which contains bracketed
 *                            content to parse.<br>
 *
 * @param desiredDepth        (Integer) Default is 0 (full depth). The
 *                            nested depth to retrieve bracketed content
 *                            from.<br> If the bracket depth supplied is
 *                            deeper than what is contained within the
 *                            supplied input string then an <b>IllegalArgu-
 *                            mentException</b> is thrown explaining as
 *                            such.
 *
 * @param bracketType         (String) You must supply the bracket type to
 *                            process or null to use the default bracket 
 *                            type of parentheses ("()"). You can provide 
 *                            the bracket type to work against by supplying 
 *                            either a single open or close bracket or both 
 *                            open and close brackets, for example, any one 
 *                            of the following are all acceptable entries if
 *                            parentheses are required:<pre>
 *
 *                                  "("     ")"     "()"    ")("</pre><br>
 *
 * Any one of four (4) bracket types can be supplied. The allowable Bracket
 * Types are:<pre>
 *
 *      ()      Parentheses
 *      {}      Curly Braces
 *      []      Square Brackets
 *      &lt;&gt;      Chevron Brackets</pre>
 *
 * @param removeOuterBrackets (Optional - Boolean - Default is false) By
 *                            default the outer brackets for each found
 *                            group are also attached to the returned
 *                            results. If true is supplied to this optional
 *                            parameter then the outer brackets are removed
 *                            from the returned group results.<br>
 *
 * @return (1D String Array) The determined nested groups desired.<br>
 *
 * @throws IllegalArgumentException if a depth is supplied greater than the
 *                                  available bracketed depth contained
 *                                  within the supplied input string. This
 *                                  exception is also thrown if it is found
 *                                  that the supplied Bracket Type is
 *                                  unbalanced (open and closed braces are
 *                                  not properly paired) within the supplied
 *                                  input string.
 */
public String[] getNestedBracketedGroups(String bracketedString, int desiredDepth,
        String bracketType, boolean... removeOuterBrackets) {
    boolean removeOuter = false;
    if (removeOuterBrackets.length > 0) {
        removeOuter = removeOuterBrackets[0];
    }

    int d = bracketsMaxDepth(bracketedString, bracketType);
    if (desiredDepth == 0) {
        //Default for this method is 0 (full depth).
        desiredDepth = 1;
    }
    if (d == -1) {
        // Throw Exception...
        throw new IllegalArgumentException("\n\ngetNestedBracketedGroups() Method Error!\n"
                + "Brackets mismatch in supplied string!\n");
    }
    else if (d < desiredDepth) {
        // Throw Another Exception...
        throw new IllegalArgumentException("\n\ngetNestedBracketedGroups() Method Error!\n"
                + "Invalid Depth Supplied! Brackets within the supplied string go to a\n"
                + "maximum depth of (" + d + ") and therefore can not go to the supplied "
                + "depth\nof (" + desiredDepth + "). Change the desired depth.\n");
    }

    
    char open = '(';    // Default
    char close = ')';   // Default
    String bType = Character.toString(open);
    if (bracketType != null && !bracketType.trim().isEmpty()) {
        bType = Character.toString(bracketType.trim().charAt(0));
    }
    
    switch (bType) {
        case "(":
        case ")":
            open = '(';
            close = ')';
            break;
        case "{":
        case "}":
            open = '{';
            close = '}';
            break;
        case "[":
        case "]":
            open = '[';
            close = ']';
            break;
        case "<":
        case ">":
            open = '<';
            close = '>';
            break;
        default:
            throw new IllegalArgumentException("\ngetNestedBracketedGroups() Method Error!\n"
                    + "Unknown bracket type supplied (" + bType + ")!\n");
    }

    List<String> list = new ArrayList<>();
    int n = bracketedString.length();
    char[] c = bracketedString.toCharArray();
    int depth = 0;
    String strg = "";
    for (int i = 0; i < n; i++) {
        if (c[i] == open) {
            depth++;
        }
        if ((depth >= desiredDepth)) {
            if (c[i] == close) {
                depth--;
            }
            strg += Character.toString(c[i]);

            if (depth < desiredDepth) {
                strg = strg.trim();
                if (removeOuter) {
                    if (strg.startsWith(Character.toString(open))) {
                        strg = strg.substring(1);
                    }
                    if (strg.endsWith(Character.toString(close))) {
                        strg = strg.substring(0,
                                strg.lastIndexOf(Character.toString(close)));
                    }
                }
                list.add(strg);
                strg = "";
            }

            continue;
        }
        if (c[i] == close) {
            depth--;
        }
        if (!strg.isEmpty()) {
            strg = strg.trim();
            if (removeOuter) {
                if (strg.startsWith(Character.toString(open))) {
                    strg = strg.substring(1);
                }
                if (strg.endsWith(Character.toString(close))) {
                    strg = strg.substring(0,
                            strg.lastIndexOf(Character.toString(close)));
                }
            }
            list.add(strg);
            strg = "";
        }
    }
    if (!strg.isEmpty()) {
        strg = strg.trim();
        if (removeOuter) {
            if (strg.startsWith(Character.toString(open))) {
                strg = strg.substring(1);
            }
            if (strg.endsWith(Character.toString(close))) {
                strg = strg.substring(0,
                        strg.lastIndexOf(Character.toString(close)));
            }
        }
        list.add(strg); 
    }
    
    return list.toArray(new String[list.size()]);
}


/**
 * This method takes a string and returns the maximum depth of nested
 * brackets. The bracket type to check the depth for is supplied within the
 * bracketType parameter.<br><br>
 *
 * @param bracketedString (String) The string to process.<br>
 *
 * @param bracketType     (String - Default is "()") Either a open bracket,
 *                        or a close bracket, or both open and closed
 *                        brackets can be supplied (no white-spaces). This
 *                        method will process any <b>one</b> of 4 different
 *                        bracket types and they are as follows:<pre>
 *
 *      ()      Parentheses       (Default)
 *      {}      Curly Braces
 *      []      Square Brackets
 *      &lt;&gt;      Chevron Brackets</pre>
 *
 * @return (Integer) The maximum depth of the supplied bracket type. 0 is
 *         returned if there are no brackets of the type supplied within the
 *         supplied string. -1 is returned if there is an unbalance within
 *         the supplied string of the supplied bracket type. For every open
 *         bracket there must be a close bracket and visa versa.
 */
public static int bracketsMaxDepth(String bracketedString, String... bracketType) {
    char open = '(';    // Default
    char close = ')';   // Default
    if (bracketType.length > 0) {
        String bType = Character.toString(bracketType[0].charAt(0));
        switch (bType) {
            case "(":
            case ")":
                open = '(';
                close = ')';
                break;
            case "{":
            case "}":
                open = '{';
                close = '}';
                break;
            case "[":
            case "]":
                open = '[';
                close = ']';
                break;
            case "<":
            case ">":
                open = '<';
                close = '>';
                break;
            default:
                throw new IllegalArgumentException("\nbracketsMaxDepth() Method Error!\n"
                        + "Unknown bracket type supplied (" + bType + ")!\n");
        }
    }

    int current_max = 0; // current count
    int max = 0;    // overall maximum count
    int n = bracketedString.length();
    char[] c = bracketedString.toCharArray();

    // Traverse the input string
    for (int i = 0; i < n; i++) {
        if (c[i] == open) {
            current_max++;
            // update max if required
            if (current_max > max) {

                max = current_max;
            }
        }
        else if (c[i] == close) {
            if (current_max > 0) {
                current_max--;
            }
            else {
                return -1;
            }
        }
    }

    // finally check for unbalanced string
    if (current_max != 0) {
        return -1;
    }
    return max;
}
String string = "('fdmg') (R:Percentual ('dmg') (20))";
System.out.println("String with parentheses: " + string);
int maxBracketDepth = bracketsMaxDepth(string, "()");
System.out.println("Depth of nested parentheses: " + maxBracketDepth);
System.out.println();
    
System.out.println("WITH BRACKETS:");
System.out.println("==============");
for (int i = 1; i <= maxBracketDepth; i++) {
    String[] a = getNestedBracketedGroups(string, i, "()");
    System.out.println("Parenthesized groups at depth: " + i);
    for (String b : a) {
        System.out.println(b);
    }
    System.out.println();
}
    
System.out.println("WITHOUT BRACKETS:");
System.out.println("=================");
for (int i = 1; i <= maxBracketDepth; i++) {
    String[] a = getNestedBracketedGroups(string, i, "()", true);
    System.out.println("Parenthesized groups at depth: " + i);
    for (String b : a) {
        System.out.println(b);
    }
    System.out.println();
}
String with parentheses: ('fdmg') (R:Percentual ('dmg') (20))
Depth of nested parentheses: 2

WITH BRACKETS:
==============
Parenthesized groups at depth: 1
('fdmg')
(R:Percentual ('dmg') (20))

Parenthesized groups at depth: 2
('dmg')
(20)

WITHOUT BRACKETS:
=================
Parenthesized groups at depth: 1
'fdmg'
R:Percentual ('dmg') (20)

Parenthesized groups at depth: 2
'dmg'
20