Java 正则表达式字符串拆分使一个字符优先于另一个字符
我知道有很多regex帖子,但我无法找到我真正需要的。我正在创建一个计算器应用程序,我有一个方程式,我需要根据方程式中的运算符对其进行标记 示例: “123x849-302+450”->[“123”、“849”、“302”、“450”] “124x(145+301)x402+(-402)”->[“124”、“145+301”、“402”和“-402”] “124x((234+403)/354))+(-21)”->[“124”、“(234+403)/354”、“-21”] 基本上,如果有括号,我需要在括号内获取标记,否则只需根据运算符进行拆分 我对正则表达式很不熟悉,只知道最基本的内容。我不知道如何在正则表达式中包含括号,现在,我只知道:Java 正则表达式字符串拆分使一个字符优先于另一个字符,java,regex,Java,Regex,我知道有很多regex帖子,但我无法找到我真正需要的。我正在创建一个计算器应用程序,我有一个方程式,我需要根据方程式中的运算符对其进行标记 示例: “123x849-302+450”->[“123”、“849”、“302”、“450”] “124x(145+301)x402+(-402)”->[“124”、“145+301”、“402”和“-402”] “124x((234+403)/354))+(-21)”->[“124”、“(234+403)/354”、“-21”] 基本上,如果有括号,我需
String delim = "[x+/-]";
String[] tokens = equation.toString().split(delim);
toString的存在是因为equation是一个StringBuilder。我认为regexp不是合适的工具。我不知道最终目标是什么,但如果您只需要像问题中那样拆分表达式,您可以尝试以下方法:
private static List<String> splitExpr(String expr) {
List<String> result = new ArrayList<>();
StringBuilder buf = new StringBuilder();
int level = 0;
int st = 0;
for (char c: expr.toCharArray()) {
if (level > 0) {
// we're in a subexpression
if (c == '(') {
++level;
} else if (c == ')') {
--level;
}
if (level == 0) {
result.add(buf.toString());
st = 2;
} else {
buf.append(c);
}
} else {
switch (st) {
case 0:
// initial state
if (Character.isDigit(c)) {
// first digit of a number
buf.setLength(0);
buf.append(c);
st = 1;
} else if (c == '(') {
// beginning of a subexpression
buf.setLength(0);
++level;
} else {
// error: ignore unexpected character
}
break;
case 1:
// inside a number
if (Character.isDigit(c)) {
// next digit
buf.append(c);
} else if (c == '+' || c == '-' || c == 'x' || c == 'X'
|| c == '/') {
// operator; the number is finished, add it to the list
result.add(buf.toString());
st = 0;
} else {
// error: ignore unexpected character
}
break;
case 2:
// after a subexpression
if (c == '+' || c == '-' || c == 'x' || c == 'X'
|| c == '/') {
st = 0;
} else {
// error: ignore unexpected character
}
break;
}
}
}
if (level == 0 && st == 1) {
// in a number at the end of string: add the number to the list
result.add(buf.toString());
}
return result;
}
“规则”语法的概念是一个学术概念正则表达式的名称正确:它们可以解析任何“正则”语法,但不能用于解析非正则语法 让我们将“基础数学”定义为数字、4个运算符:
+-*/
和括号的组合
“基础数学”不是正规的
因此,它不能用正则表达式进行解析
您需要的是一个解析器,它可以:
a+x*y+(b-c)*e
在该数据结构中:
PLUS
/ \
PLUS TIMES
/ \ / \
a TIMES MINUS e
/ \ / \
x y b c
可以使用各种解析器技术,例如递归下降或packrat(例如使用grappa/parboiled解析器库),以及各种基于LALR和LL(k)的解析技术,例如ANTLR。一般来说,这些都是非常复杂的技术;也许对于这种琐碎的事情,您可以为此编写自己的基于递归下降的解析
但是,回到你原来的问题,如果你想把a+x*y+(b-(g+h))*e
分成:[a'、[x'、[y'、“(b-(g+h))、[e'],这只是你需要的部分,因为现在你仍然需要解决如何处理“(b-(g+h))节点,正则表达式根本无法做到这一点:你想让你的正则表达式看到开头(
就在b
之前,作为括号块的开始,然后….正则表达式必须计算开始部分的数量,然后找到尽可能多的结束部分并忽略它们,然后在这些结束部分胜出后再计算结束部分。因此,此正则表达式:
String elementPattern = "(\\([^\\)]+\\)|[^-+*/\\(\\)]+)";
Pattern p = Pattern.compile("^\\s*" + elementPattern + "(\\s*[-+*/]\\s*" + elementPattern + ")*$");
乍一看似乎能完成任务,但实际上却不能完成任务:它会停止考虑
(b-(g+h))部分在2个关闭的括号中的第一个,因此不能匹配。它需要在第二个停止,但是正则表达式没有任何方式去做,因为这不是“正则”。< /P>也许不是你需要的ReGEXP……我还能用什么?模式匹配器?我也不熟悉。我会使用递归下降法。谢谢你把这件事弄清楚!我会好好读一读的。
String elementPattern = "(\\([^\\)]+\\)|[^-+*/\\(\\)]+)";
Pattern p = Pattern.compile("^\\s*" + elementPattern + "(\\s*[-+*/]\\s*" + elementPattern + ")*$");