繁体   English   中英

用于验证数学表达式的正则表达式

[英]Regular Expression to Validate a Math Expression

我正在尝试确定给定的输入是否为有效的数学表达式。 这是我目前想出的代码,但是只有Input为单个整数(例如100、200、5、7)时,它才返回true。

Pattern pattern = Pattern.compile("-?\\w+|[-+*%/()]");
Matcher match = pattern.matcher(Input);

if(pattern.matcher(Input).matches())
{
    System.out.print("True");
}
else
    System.out.print("False");

有关我要完成的工作的更多信息:

为简单起见, 假设整数 (因此,不包含变量和小数位)。
运算符为:+,-,*,/,%。
仅带括号(因此没有括号或花括号)。

例子:

有效:

123  
1*2(3+4)%7  
3--4+5*-7  
13(12)+11-(7*15%(11-2)/4)  
(((((-99999)))))

无效

1+2)  
)5--  
3+*12  
)(++**//
(50)+12)

另外,如果可能的话,是否还可以包含有关Regex工作原理的简单解释? 我对这个话题很陌生。 我从概念上理解它,但是在我的代码中难以实现。

如几条评论所述, 使用正则表达式匹配是您无法要求的。 实际上,匹配的平衡括号是经典的“简单的正则表达式无法解决的问题”之一。 只要您的数学表达式可以包含任意嵌套的括号,就不能使用正则表达式对其进行验证。

然而,就可以验证一个较小的语言,然后我们可以构建成与编码的一点点您的语言的验证程序。 较小的语言与您的语言一样,但有一个变化: 不允许使用括号 然后,该语言中的有效表达式如下所示:

INTEGER OP INTEGER OP INTEGER OP .... OP INTEGER

另一种说法是“一个INTEGER后跟零个或多个OP INTEGER序列”。 可以将其转换为正则表达式,例如:

Pattern simpleLang = Pattern.compile("-?\\d+([-+*%/]-?\\d+)*");

所以-?\\d+表示INTEGER[-+*%/]表示OP 好的,现在我们该如何使用呢? 好吧,首先让我们对其进行修改,以在整数之间添加任意空格,并使模式成为static ,因为我们将把此验证逻辑包装在一个类中:

static Pattern simpleLang = Pattern.compile("\\s*-?\\d+(\\s*[-+*%/]\\s*-?\\d+)*\\s*");

(但请注意,我们不允许一个负号和它后面的号码之间的空格,所以3 - - 4是不允许的,即使3 - -4是允许的)

现在,要验证完整语言,我们需要做的是重复查找位于最内括号级别的块(因此,一个块本身不包含任何括号,但被一个开闭括号对包围),请验证parens与简单语言匹配,然后用一些整数(用空格包围)替换该块(包括周围的paren),以便将其与周围的东西分开。 所以逻辑是这样的:

  • expr进来是11 - (7 * 15 % (11 - 2) / 4)
  • 最里面的括号块是11 - 2
  • 请问11 - 2比赛的简单的语言? 是!
  • 用一些整数替换(11 - 2) 例如,使用1
  • expr现在是11 - (7 * 15 % 1 / 4)
  • 最里面带括号的块是7 * 15 % 1 / 4
  • 7 * 15 % 1 / 4与简单语言匹配? 是!
  • 用一些整数替换(7 * 15 % 1 / 4) 例如,使用1
  • expr现在是11 - 1
  • 不用了,请问: expr与简单语言匹配? 是!

在代码中,它可以做到:

static Pattern simpleLang = Pattern.compile("\\s*-?\\d+(\\s*[-+*%/]\\s*-?\\d+)*\\s*");
static Pattern innerParen = Pattern.compile("[(]([^()]*)[)]");
public static boolean validateExpr(String expr) {
    while (expr.contains(")") || expr.contains("(")) {
        Matcher m = innerParen.matcher(expr);
        if (m.find()) {
            if (!simpleLang.matcher(m.group(1)).matches()) {
                return false;
            }
            expr = expr.substring(0,m.start()) + " 1 " + expr.substring(m.end());
        } else {
            // we have parens but not an innermost paren-free region
            // This implies mismatched parens
            return false;
        }
    }
    return simpleLang.matcher(expr).matches();
}

请注意,有一个您称为“有效”的表达式,它不会称为有效:即表达式13(12)+11-(7*15%(11-2)/4) 这将被视为无效,因为在13和12之间没有运算符。如果您希望允许这种隐式乘法,最简单的方法是添加 (空格字符)作为简单语言中允许的运算符,因此请将simpleLang更改为:

static Pattern simpleLang = Pattern.compile("\\s*-?\\d+(\\s*[-+ *%/]\\s*-?\\d+)*\\s*");

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM