【问题标题】:Splitting a simple maths expression with regex用正则表达式拆分一个简单的数学表达式
【发布时间】:2011-03-23 09:07:01
【问题描述】:

我正在尝试使用运算符 - + * / 在 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 regex math


【解决方案1】:

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

【讨论】:

  • 嗨,但是我还需要包括运算符,所以我不能使用你给的正则表达式
  • 通过括号存储匹配。
【解决方案2】:

使用匹配,而不是拆分:

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

此正则表达式还将接受有效的浮点数,例如:1.2e+3 * 2,它应该等于 2400。其他受访者给出的正则表达式将失败。

【讨论】:

  • 这也适用于负数吗?你将如何在 Java 中使用它来分割你的字符串?
【解决方案3】:
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

您还可以使用 ?: 来避免捕获组。我留下它是为了让它变得简单。

【讨论】:

    【解决方案4】:

    您可以使用零宽度匹配的lookahead 和lookbehind 组合作为替代。

    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, )]
    

    说明

    • […] 是一个字符类定义
    • (?&lt;=…) 是向后看;它断言我们可以将 匹配到左侧
    • (?=…) 是前瞻;它断言我们可以将 匹配到右侧
    • this|that 是交替
    • 因此,(?&lt;=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]"
    

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

    相关问题

    【讨论】:

    • 很棒的帖子,但我想知道:如何避免拆分负数?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-05-02
    • 1970-01-01
    • 2014-06-02
    • 2020-01-14
    • 2016-01-17
    • 2019-02-27
    相关资源
    最近更新 更多