【问题标题】:Validate mathematical expressions using regular expression?使用正则表达式验证数学表达式?
【发布时间】:2021-08-20 10:09:10
【问题描述】:

我想使用正则表达式验证数学表达式。数学表达式可以是这样的

  1. 可以为空表示不输入任何内容

  2. 如果指定,它将始终以运算符 +-*/ 开头,并且始终后跟一个可以包含的数字 任意位数,数字可以是十进制(在数字之间包含.)或整数(数字中没有'.'符号)。 示例:*0.9+22.36- 90/ 0.36365

  3. 之后可以是第 2 点中提到的内容(上一行)。 示例:*0.9+5+22.36*4/56.33-90+87.25/22/0.36365/4+2.33

请帮帮我。

【问题讨论】:

  • - *0.9+5 不在您的问题定义范围内。此外,它还为您的表达式添加了递归性质。
  • @Jason McCreary - 是的,我在第 3 点中提到它可以是递归的。
  • 这不符合你原来的例子。但我看到您在编辑中删除了- 和空格。所以现在它们是对齐的。

标签: regex


【解决方案1】:

这样的事情应该可以工作:

^([-+/*]\d+(\.\d+)?)*

Regexr Demo

  • ^ - 字符串的开头
  • [-+/*] - 这些运营商之一
  • \d+ - 一个或多个数字
  • (\.\d+)? - 一个可选的点,后跟一个或多个数字
  • ()* - 整个表达式重复了零次或多次

【讨论】:

  • @Jason McCreary - 请看一下示例,我的意思是第一个“-”是连字符而不是减法符号。
  • @Bibhu 是的,起初我以为它是一个简单的连字符,而您写道它总是以运算符开头,后跟一个数字,所以减号不适合那里:)。
  • @bažmegakapa - 我想在我的正则表达式中允许括号,比如 *5-(4-8)。我试过regexr.com?31e21但没有成功,它也接受*5-4-8)和*5-(4-8不正确,需要你的帮助。
  • @Bibhu 问个问题怎么样? :)
  • @bažmegakapa - 我在这里添加了一个问题*.com/questions/11323493/…
【解决方案2】:

您可以尝试使用moo 等生成这样的正则表达式:

(?:(?:((?:(?:[ \t]+))))|(?:((?:(?:\/\/.*?$))))|(?:((?:(?:(?<![\d.])[0-9]+(?![\d.])))))|(?:((?:(?:[0-9]+\.(?:[0-9]+\b)?|\.[0-9]+))))|(?:((?:(?:(?:\+)))))|(?:((?:(?:(?:\-)))))|(?:((?:(?:(?:\*)))))|(?:((?:(?:(?:\/)))))|(?:((?:(?:(?:%)))))|(?:((?:(?:(?:\()))))|(?:((?:(?:(?:\)))))))

此正则表达式匹配任意数量的 int、float、大括号、空格和运算符 +-*/%

但是,2+ 等表达式仍将由正则表达式验证,因此您可能希望改用解析器。

【讨论】:

    【解决方案3】:

    如果你想要消极或积极的表达,你可以这样写>
    ^\-?[0-9](([-+/*][0-9]+)?([.,][0-9]+)?)*?$

    还有第二个
    ^[(]?[-]?([0-9]+)[)]??([(]?([-+/*]([0-9]))?([.,][0-9]+)?[)]?)*$

    表达式中有括号,但不计算您需要验证它的方法或正则表达式的数量。 // 方法

     public static bool IsPairParenthesis(string matrixExpression)
        {
            int numberOfParenthesis = 0;
            foreach (char character in matrixExpression)
            {
                if (character == '(')
                {
                    numberOfParenthesis++;
                }
                if (character == ')')
                {
                    numberOfParenthesis--;
                }
            }
    
            if (numberOfParenthesis == 0)
            { return true; }
            return false;
        }
    

    【讨论】:

      【解决方案4】:

      这是 java 正则表达式,但只有在没有大括号的情况下才有效

      [+\-]?(([0-9]+\.[0-9]+)|([0-9]+\.?)|(\.?[0-9]+))([+\-/*](([0-9]+\.[0-9]+)|([0-9]+\.?)|(\.?[0-9]+)))*
      

      在java代码中也有大括号
      在这种情况下,我将 (..) 替换为数字 (..),应该匹配没有大括号模式

          //  without brace pattern
          static Pattern numberPattern = Pattern.compile("[+\\-]?(([0-9]+\\.[0-9]+)|([0-9]+\\.?)|(\\.?[0-9]+))([+\\-/*](([0-9]+\\.[0-9]+)|([0-9]+\\.?)|(\\.?[0-9]+)))*");
          static Pattern bracePattern = Pattern.compile("\\([^()]+\\)");
      
          public static boolean matchesForMath(String txt) {
      
              if (txt == null || txt.isEmpty()) return false;
              txt = txt.replaceAll("\\s+", "");
              if (!txt.contains("(") && !txt.contains(")")) return numberPattern.matcher(txt).matches();
              if (txt.contains("(") ^ txt.contains(")")) return false;
              if (txt.contains("()")) return false;
      
              Queue<String> toBeRematch = new ArrayDeque<>();
              toBeRematch.add(txt);
              while (toBeRematch.size() > 0) {
                  String line = toBeRematch.poll();
                  Matcher m = bracePattern.matcher(line);
                  if (m.find()) {
                      String newline = line.substring(0, m.start()) + "1" + line.substring(m.end());
                      String withoutBraces = line.substring(m.start() + 1, m.end() - 1);
                      toBeRematch.add(newline);
                      if (!numberPattern.matcher(withoutBraces).matches()) return false;
                  }
      
              }
              return true;
          }
      

      【讨论】: