我正在尝试在||
,&&
和()
上拆分字符串,但我无法在嵌套的括号中正确拆分。
示例字符串:
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
)
基本上,我正在尝试对表达式进行标记化,并且我只想在它们包含包含>
,>=
,==
的完整语句的情况下拆分括号,等
答案 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(")");
}
}