Java字符串与正则表达式分开

时间:2015-10-21 21:45:57

标签: java regex

我正在尝试拆分表示为String的算术等式,我想保留多字符分隔符:{==, !=, >=, <=, >, <}

这就是我所拥有的:

String expression = "2*(5 +1)- 3 * 2 >= 6^3.1 + 5";
expression = expression.replaceAll("\\s", "");
String[] parsedExpression = expression.split("((?<===)|(?===))|"
            + "((?<=>=)|(?=>=))|"
            + "((?<=!=)|(?=!=))|"
            + "((?<=<=)|(?=<=))|"
            + "((?<=>)|(?=>))|"
            + "((?<=<)|(?=<))");

然而它会像这样拆分:

[2*(5+1)-3*2, >, =, 6^3.1+5]

当所需的分割是这样的时候:

[2*(5+1)-3*2, >=, 6^3.1+5]

我猜测问题是我的规则是使用><作为导致问题的分隔符,但我不知道如何修复它。

4 个答案:

答案 0 :(得分:1)

(?!=)<外观添加否定预测>,以确保=成为运营商的一部分时不匹配:

String[] parsedExpression = expression.split("((?<===)|(?===)|"
        + "(?<=>=)|(?=>=)|"
        + "(?<=!=)|(?=!=)|"
        + "(?<=<=)|(?=<=)|"
        + "(?<=>(?!=))|(?=>(?!=))|"   // See here
        + "(?<=<(?!=))|(?=<(?!=)))"); // and here

请参阅IDEONE demo

System.out.println(Arrays.toString(parsedExpression));打印[2*(5+1)-3*2, >=, 6^3.1+5]

答案 1 :(得分:0)

表达式中只能有一个标记(“&gt;”,“&gt; =”,“==”等)吗?你是否允许“5&lt; 6&lt; 7&lt; 7”这样的东西?

虽然它不使用正则表达式,但您可以尝试这样的事情。

String[] parsedExpression = new String[3]; // assuming form "3 < 4". may need to modify a little
String[] tokens = {"==", "!=", "<", ">", "<=", ">="};

int idxOfToken = expression.indexOf(try every token until one is present);
String comparOp = ""; // set to operator you found
int additional = comparOp.length() == 2 ? 2 : 1;

parsedExpression[0] = expression.substring(0, idxOfToken);
parsedExpression[1] = comparOp;
parsedExpression[2] = expression.substring(idxOfToken + additional);

答案 2 :(得分:0)

因为你在宽度为零的外观上分裂,即使你最初匹配一个两个字符的模式,匹配位置也不会超过整个模式。相反,您可以匹配模式的其他部分。

因此,即使您最初匹配:>=,其中的=也会匹配第二次。

虽然可以使用看似分散的方法来解决您的问题,但它却是一个难以理解的正则表达式。采用不同的方法会更好,更简单。

例如,您可以匹配分隔符或非分隔符:

/[^><=]+|[><=]+/

此类模式的所有匹配列表将根据需要拆分字符串。这会对您的输入数据做出某些假设,但如果需要可以轻松调整。例如,它可以扩展为仅匹配有效的分隔符。

查看工作here

答案 3 :(得分:0)

更新1:第4种模式无法正常工作。

您希望仅在以下内容之前和之后进行拆分:==!=>=<=><, (为清楚起见,例如使用COMMENTS / (?x)):

  • (?= [=!]= ):在==之前,!=
  • (?= [><] ):在>之前,<(包括>=<=
  • (?<= [=!><]= )==之后,!=>=<=
  • 之后
  • (?<= [><](?!=) )>之后,<,后面没有=

前两个可以使用|作为(?= [=!]= | [><] )进行组合 最后两个可以使用|作为(?<= [=!><]= | [><](?!=) )进行组合。

所以,所有组合使用(?= [=!]= | [><] ) | (?<= [=!><]= | [><](?!=) )使用COMMENTS标志,或者只是:

(?=[=!]=|[><])|(?<=[=!><]=|[><](?!=))

测试

String regex = "(?=[=!]=|[><])|(?<=[=!><]=|[><](?!=))";
String[] split = "2*(5+1)-3*2 >= 6^3.1+5".split(regex);
System.out.println(Arrays.toString(split));

split = "a == b != c >= d <= e > f < g = h ! i".split(regex);
System.out.println(Arrays.toString(split));

输出

[2*(5+1)-3*2 , >=,  6^3.1+5]
[a , ==,  b , !=,  c , >=,  d , <=,  e , >,  f , <,  g = h ! i]

更新2

要获得完整的答案,我想根据Pushkindan1111的想法展示一个解决方案,即找到运营商。

模式更简单,更容易理解。可能也表现得更好。

String text = "2*(5+1)-3*2 >= 6^3.1+5";
Matcher m = Pattern.compile("[=!]=|[><]=?").matcher(text);
if (m.find()) {
    String left  = text.substring(0, m.start());
    String oper  = m.group(); // or text.substring(m.start(), m.end());
    String right = text.substring(m.end());
    System.out.printf("[%s, %s, %s]%n", left, oper, right);
}

输出

[2*(5+1)-3*2 , >=,  6^3.1+5]