在多个标记上拆分带有嵌套括号的字符串

时间:2017-07-31 16:59:40

标签: java regex

我正在尝试在||&&()上拆分字符串,但我无法在嵌套的括号中正确拆分。

示例字符串:

q1 == false || ( q1 == true && q3 != null && ( method(param) - method() ) > 120 )

我目前的正则表达式/代码:

String[] tempTokens = input.split("(?=([|]{2}|[&]{2}|[(]|[)]))|(?<=([|]{2}|[&]{2}|[(]|[)]))");

for (String token : tempTokens) {
    if (token.trim().length() > 0) {
        System.out.println(token.trim());
    }
}

当前输出:

q1 == false
||
(
q1 == true
&&
q3 != null
&&
(
method
(
param
)
- method
(
)
)
> 120
)

通缉输出:

q1 == false
||
(
q1 == true
&&
q3 != null
&&
( method(param) - method() ) > 120
)

基本上,我正在尝试对表达式进行标记化,并且我只想在它们包含包含>>===的完整语句的情况下拆分括号,等

4 个答案:

答案 0 :(得分:1)

谢谢大家的建议!在不使用正则表达式的情况下解析表达式肯定更容易。

我使用修改后的Shunting-yard算法将表达式转换为后缀表示法,然后从中构建一个树。

public class ExpressionTreeNode {

    private ExpressionTreeNode left, right;
    private String content;

    public ExpressionTreeNode(ExpressionTreeNode left, ExpressionTreeNode right, String content) {
        this.left = left;
        this.content = content;
        this.right = right;
    }
}

创建树方法:

private static ExpressionTreeNode createExpressionTree(String[] tokens) {
    final Stack<ExpressionTreeNode> nodes = new Stack<ExpressionTreeNode>();

    for (int i = 0; i < tokens.length; i++) {
        String token = tokens[i];

        if (Operator.isOperator(token)) {
            ExpressionTreeNode rightNode = nodes.pop();
            ExpressionTreeNode leftNode = nodes.pop();
            nodes.push(new ExpressionTreeNode(leftNode, rightNode, token));
        } else {
            nodes.add(new ExpressionTreeNode(null, null, token));
        }
    }

    return nodes.pop();
}

用法:

// here convert to postfix notation
String[] tempTokens = part.split(" ");
String[] output = infixToPostfix(tempTokens);

ExpressionTreeNode root = createExpressionTree(output);

由于所有操作(不只是||&&)分离到节点,树木非常庞大,但它对我有用。

问题中示例的输出:

                 /----- 120
         /----- >
         |       |       /----- method()
         |       \----- -
         |               \----- method(param)
 /----- &&
 |       |               /----- null
 |       |       /----- !=
 |       |       |       \----- q3
 |       \----- &&
 |               |       /----- true
 |               \----- ==
 |                       \----- q1
||
 |       /----- false
 \----- ==
         \----- q1

答案 1 :(得分:0)

也许使用模式/匹配器可以让你关闭

        String txt="( method(param) - method() ) >= 120";

    String re1="(\\()"; // Single Character (
    String re2="(\\s+)";    // White Space 1
    String re3="((?:[a-z][a-z0-9_]*))"; // Variable Name method
    String re4="(\\()"; //  Single Character (
    String re5="((?:[a-z][a-z0-9_]*))"; // Variable Name param
    String re6="(\\))"; // Single Character )
    String re7="( )";   // White Space 
    String re8="(-)";   // Single Character -
    String re9="( )";   // White Space 
    String re10="((?:[a-z][a-z0-9_]*))";    // Variable Name method
    String re11="(\\()";    //  Single Character (
    String re12="(\\))";    //  Single Character )
    String re13="( )";  // White Space 
    String re14="(\\))";    //  Single Character )
    String re15="( )";  // White Space
    String re16="(..?)";    // Any 1 or 2 Characters > >= ==
    String re17="( )";  // White Space 
    String re18="(\\d+)";   // Integer 120 

    Pattern p = Pattern.compile(re1+re2+re3+re4+re5+re6+re7+re8+re9+re10+re11+re12+re13+re14+re15+re16+re17+re18,Pattern.CASE_INSENSITIVE | Pattern.DOTALL);
    Matcher m = p.matcher(txt);
    if (m.find())
    {
        String c1=m.group(1);
        String ws1=m.group(2);
        String var1=m.group(3);
        String c2=m.group(4);
        String var2=m.group(5);
        String c3=m.group(6);
        String ws2=m.group(7);
        String c4=m.group(8);
        String ws3=m.group(9);
        String var3=m.group(10);
        String c5=m.group(11);
        String c6=m.group(12);
        String ws4=m.group(13);
        String c7=m.group(14);
        String ws5=m.group(15);
        String c8=m.group(16);
        String ws6=m.group(17);
        String int1=m.group(18);
        System.out.println(c1.toString() + ws1.toString() + var1.toString() + c2.toString() + var2.toString() +c3.toString()+ws2.toString()+c4.toString()+ws3.toString()+var3.toString()+c5.toString()+c6.toString()+ws4.toString()+c7.toString()+ws5.toString()+c8.toString()+ws6.toString()+int1.toString()+"\n");
    }

答案 2 :(得分:-1)

我认为您无法正确解析带有正则表达式的字符串。我希望你想要评估这种字符串的一部分。这就是你可能想要查找AST的地方 - 抽象语法树,解析器生成器。对于С语言,它是lex + yacc。对于java,它是antlr或javacc。我已经处理过他们。

答案 3 :(得分:-1)

对于非常特殊的解决方案,您可以使用:(编辑,更好的编码)

    var s = "q1 == false || ( q1 == true && q3 != null && ( method(param) - method() ) > 120 )";
    var result = new List<string>();
    Parse(result, s);


    void Parse(List<string> result, string s)
    {
        var currentSplitter = string.Empty;
        var listOfSplitters = new string[] { "||", "&&" };
        var splitterPosition = -1;

        for (var i = 0; i < listOfSplitters.Length; i++)
        {
            currentSplitter = listOfSplitters[i];
            splitterPosition = s.IndexOf(currentSplitter);
            if (splitterPosition > -1)
            {
                break;
            }
        }

        if (splitterPosition == -1) //not found
        {
            result.Add(s);
            return;
        }

        var parenthesisPosition = s.IndexOf("(");
        if (parenthesisPosition == -1) //no more parenthesis
        {
            result.Add(s);
        }
        else if(parenthesisPosition > splitterPosition) //there is a parenthesis, but it's after a splitter
        {
            result.Add(s.Substring(0,splitterPosition-1));
            result.Add(currentSplitter);
            Parse(result, s.Substring(splitterPosition + currentSplitter.Length, s.Length - splitterPosition - currentSplitter.Length));
        }
        else //there is a parenthesis
        {
            result.Add("(");
            var lastpar = s.LastIndexOf(')');
            var sub = s.Substring(parenthesisPosition+1, lastpar -2);
            Parse(result, sub);
            result.Add(")");
        }
    }