使用正则表达式分割简单的数学表达式

3
我正在尝试使用正则表达式来拆分像1.5+4.2*(5+2)这样的带有- + * /运算符的方程,以便将输出输入到数组中,以便我可以逐个解析。
[0]1.5
[1]+
[2]4.2
[3]*
[4](
[5]5
[6]+
[7]2
[8]) 

我发现 \b 可以在 1+2+3 上正常工作,但如果有小数点,它就无法分割。
我尝试使用 \b(\.\d{1,2}) 进行分割,但它无法在小数点上进行分割。

我很好奇,当你拥有不同的部分时,你打算做什么。这可能是另一个需要对语法进行词法分析(lex / yacc)而不是通过正则表达式运行的实例吗? - Java Drinker
我知道因为个人喜好而更改标题不是我的职责,但有些人说“maths”而不是“math”这一事实让我感到烦恼。 - eshimoniak
4个回答

18

你可以使用零宽度匹配的前瞻和后顾组合作为备选项。

String equation = "1.5+4.2*(5+2)";

String regex = "(?<=op)|(?=op)".replace("op", "[-+*/()]");

// actual regex becomes (?<=[-+*/()])|(?=[-+*/()])

System.out.println(java.util.Arrays.toString(
    equation.split(regex)
));
//  ___  _  ___  _  _  _  _  _  _
// [1.5, +, 4.2, *, (, 5, +, 2, )]

解释

  • […] 是一个字符类定义。
  • (?<=…) 是向后查找,它断言我们可以匹配左边的
  • (?=…) 是向前查找,它断言我们可以匹配右边的
  • this|that 是选择。
  • 因此,(?<=op)|(?=op) 匹配在 op 之后或之前的任何位置。
    • ... 其中 op 被替换为 [-+*/()],即匹配运算符的字符类。
      • 请注意,这里首先出现的是 -,以防止它成为一个范围定义元字符。

参考资料

相关问题


更多零宽度匹配正则表达式的示例

以下是更多在零宽度匹配构造上进行拆分的示例;这可以用于拆分字符串,同时保留定界符。

简单的句子拆分,保留标点符号:

String str = "Really?Wow!This.Is.Awesome!";
System.out.println(java.util.Arrays.toString(
    str.split("(?<=[.!?])")
)); // prints "[Really?, Wow!, This., Is., Awesome!]"

使用\G将长字符串分割为固定长度的部分。

String str = "012345678901234567890";
System.out.println(java.util.Arrays.toString(
    str.split("(?<=\\G.{4})")
)); // prints "[0123, 4567, 8901, 2345, 6789, 0]"

在大写字母前拆分字符串(但第一个字母除外!)

System.out.println(java.util.Arrays.toString(
    "OhMyGod".split("(?=(?!^)[A-Z])")
)); // prints "[Oh, My, God]"

下面提供了各种示例,相关问题如下。

相关问题


很棒的帖子,但我想知道:如何避免拆分负数? - theEpsilon

6
Pattern pattern = Pattern.compile("((\\d*\\.\\d+)|(\\d+)|([\\+\\-\\*/\\(\\)]))");
Matcher m = pattern.matcher("1.5+4.2*(5+2)/10-4");
while(m.find()) {
    System.out.printf("%s ", m.group());
}

output: 1.5 + 4.2 * ( 5 + 2 ) / 10 - 4

你也可以使用 ?: 来避免捕获组。我将其保留,以使其更简单易懂。

3

使用match而非split:

(?:\d+\.)?\d*(?:e[+\-]?\d+)?|[\s\-\/()+*%=]

这个正则表达式还可以接受有效的浮点数,如:1.2e+3 * 2,其结果应为2400。其他回答者给出的正则表达式将失败。

这个方法也适用于负数吗?在Java中,你会如何使用它来分割字符串? - Narshe

0

使用[+-/*()]分割字符串。


嗨,不过我还需要包含运算符,所以不能使用你给出的正则表达式。 - sutoL
通过括号将匹配项存储。 - Jeremy L

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接