首页 > 解决方案 > 正则表达式识别Java中括号之间的表达式

问题描述

我有一个表达式作为下面的字符串:

(((status==SUBMITTED) && (submit_date>2020-01-03)) &&(dueDate<(proof_date+1)))

我想识别上述字符串中的所有内部表达式,如下所示:

(status==SUBMITTED)
(submit_date>2020-01-03)
(dueDate<(proof_date+1)

((status==SUBMITTED) && (submit_date>2020-01-03))
((status==SUBMITTED) && (submit_date>2020-01-03)) &&(dueDate<(proof_date+1))

以下是我用 Java 编写的代码:

    String expression = "((status==SUBMITTED)&&(submit_date>2020-01-03)&&(dueDate<(proof_date+1)))";

    //Matcher m = Pattern.compile("\\((.*?)\\)").matcher(expression);
    //Matcher m = Pattern.compile("\\([^()]*\\)").matcher(expression);
    Matcher m = Pattern.compile("\\(([^()]*|\\([^()]*|\\))*\\)").matcher(expression);
    while(m.find()) {
        System.out.println("Group Result: "+m.group(0));
    }

但是我没有得到组合,它只显示以下值:

Group Result: ((status==SUBMITTED)
Group Result: (submit_date>2020-01-03)
Group Result: (dueDate<(proof_date+1)

我怎样才能得到以上所有的组合。有没有可以正确识别这个的正则表达式?

标签: javaregex

解决方案


正则表达式通常不足以解决这个问题。把它想象成试图用花园软管对抗五级警报。

您对正则表达式的期望最好是一种模式,它可以找到具有特定嵌套级别的括号表达式。例如,识别((...)...(...))应该是可能的,或者(((...)...(...))..((...)..(...)))。但即使是看似简单的事情(((...)..(...))...(...))也会很困难,如果不是不可能的话。

要处理任意表达式,您需要一种比正则表达式更强大的技术。语法形式层次结构中正则表达式的下一步被称为上下文无关语法(CFG)。它们足够强大,可以处理任意数量的嵌套结构类型,彼此正确嵌套,并且嵌套到任意深度。

但是,对于带括号的表达式,您实际上不需要释放 CFG 解析器的全部功能。您所需要的只是一个堆栈,以跟踪您尚未看到匹配的右括号的左括号:

String expression = "((status==SUBMITTED)&&(submit_date>2020-01-03)&&(dueDate<(proof_date+1)))";

Stack<Integer> lpar = new Stack<>();
for (int i = 0; i < expression.length(); ++i) {
    char c = expression.charAt(i);
    if (c == '(') {
        lpar.push(i);
    } else if (c == ')') {
        if (lpar.isEmpty()){
            System.out.println("Unbalanced )");
            break;
        }
        int start = lpar.pop();
        System.out.println(expression.substring(start, i+1));
    }
}
if (!lpar.isEmpty()){
    System.out.println("Missing )");
}


推荐阅读