繁体   English   中英

用于验证算术表达式的正则表达式

[英]Regular expression for validating arithmetic expression

我有一个算术表达式

string exp = "((2+3.1)/2)*4.456";

我想通过使用正则表达式进行验证。 该表达式只能包含整数,浮点数,操作数和括号。

我如何生成正则表达式以进行验证,请帮助或提出任何其他验证该字符串的方法。

使用Perl / PCRE,我们可以借助如下结构的模式来验证这种简单的算术表达式:

expr = pnum ( op pnum )*
pnum = num | \( expr \)

其中numop根据需要定义。 例如:

num = -?+\d++(?:\.\d++)?+
op = [-+*/]

这将为我们提供以下工作表达:

(?x)^ (?&expr) $

(?(DEFINE)
    (?<expr> (?&pnum) (?: (?&op) (?&pnum) )*+   )
    (?<pnum> (?> (?&num) | \( (?&expr) \) )   )
    (?<num>  -?+\d++(?:\.\d++)?+   )
    (?<op>   [-+*/]   )
)

但是此类表达式不能与.NET正则表达式一起使用,因为它不支持(递归)后继调用(?&name) 而是.NET regex lib为我们提供了其特殊功能: 平衡组

使用平衡组,我们可以重写pnum使用的必需的递归调用,并使用如下结构:

expr = pnum ( op pnum )* (?(p)(?!))
pnum = (?> (?<p> \( )* num (?<-p> \) )* )

我们在这里所做的是在每个数字前后允许任意数量的可选打开和关闭括号,计算打开括号(?<p> \\( )的总数,从该数字减去关闭括号(?<-p> \\) )并在表达式的末尾确保开括号的数量为0 (?(p)(?!))

(我相信这等效于原始结构,不过我还没有提供任何正式的证据。)

产生以下.NET模式:

(?x)
^
(?> (?<p> \( )* (?>-?\d+(?:\.\d+)?) (?<-p> \) )* )
(?>(?:
    [-+*/]
    (?> (?<p> \( )* (?>-?\d+(?:\.\d+)?) (?<-p> \) )* )
)*)
(?(p)(?!))
$

C#示例

using System;
using System.Text.RegularExpressions;

namespace RegexTest
{
    class Program
    {
        static void Main(string[] args)
        {
            var expressions = new string[] {
                "((2+3.1)/2)*4.456",
                "1",
                "(2)",
                "2+2",
                "(1+(2+3))",
                "-2*(2+-2)",
                "1+(3/(2+7-(4+3)))",
                "1-",
                "2+2)",
                "(2+2",
                "(1+(2+3)",
            };

            var regex = new Regex(@"(?x)
                ^
                (?> (?<p> \( )* (?>-?\d+(?:\.\d+)?) (?<-p> \) )* )
                (?>(?:
                    [-+*/]
                    (?> (?<p> \( )* (?>-?\d+(?:\.\d+)?) (?<-p> \) )* )
                )*)
                (?(p)(?!))
                $
            ");

            foreach (var expr in expressions)
            {
                Console.WriteLine("Expression: " + expr);
                Console.WriteLine("    Result: " + (regex.IsMatch(expr) ? "Matched" : "Failed"));
            }
        }
    }
}

输出:

Expression: ((2+3.1)/2)*4.456
    Result: Matched
Expression: 1
    Result: Matched
Expression: (2)
    Result: Matched
Expression: 2+2
    Result: Matched
Expression: (1+(2+3))
    Result: Matched
Expression: -2*(2+-2)
    Result: Matched
Expression: 1+(3/(2+7-(4+3)))
    Result: Matched
Expression: 1-
    Result: Failed
Expression: 2+2)
    Result: Failed
Expression: (2+2
    Result: Failed
Expression: (1+(2+3)
    Result: Failed

您可以使用fslex / fsyacc在F#中编写一个简单的词法分析器。 这是一个非常接近您的要求的示例: http : //blogs.msdn.com/b/chrsmith/archive/2008/01/18/fslex-sample.aspx

暂无
暂无

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

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