2017-07-31 38 views
3

我試圖拆分||&&()上的一個字符串,並且我無法正確拆分嵌套圓括號。在多個標記上拆分一個帶有嵌套圓括號的字符串

例字符串:

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 
) 

基本上,我試圖來標記的表達,我想在括號分割只有在包含一個完整的語句包含>>===

+1

Java的正則表達式引擎沒有匹配平衡的文本(嵌套)的能力。所以,它不能匹配'(方法(參數) - 方法())' – sln

+1

這將是濫用正則表達式,並且你會寫出一個很長的,可能有問題的表達式。正則表達式用於*常規語法*。您顯示的代碼是上下文無關的。看看[常規VS上下文無關文法](https://stackoverflow.com/questions/559763/regular-vs-context-free-grammars)和[解析如果語句與正則表達式](https:// stackoverflow。com/questions/651455/regular-expression-to-identify-if-statements) –

+1

如果正則表達式看起來很複雜,那麼在下一次代碼重寫時可能會失去它,因爲下一個開發人員無法繞開邏輯或者你冒着創建時間複雜性問題的風險(我見過這種情況發生)。這意味着你應該看看如何簡化正則表達式或找到一種不同的方法來標記字符串。在你的情況下,你似乎在處理語言語法,所以一個簡單的「有限狀態機」可能是需要的方法? –

回答

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

我不認爲你會能夠正確解析這些字符串與正則表達式。我希望你想評估這樣的字符串的部分。這就是您可能想要了解AST的地方 - 抽象語法樹,解析器生成器。對於С語言,它是lex + yacc。對於java它是antlr或javacc。我已經處理了所有這些問題。

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"); 
    } 
-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(")"); 
     } 
    } 
相關問題