简体   繁体   English

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

[英]Regular expression for validating arithmetic expression

I have an arithmetic expression 我有一个算术表达式

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

I want to validate by using regular expression. 我想通过使用正则表达式进行验证。 The expression can only have integers, floating point numbers, operands and parenthesis. 该表达式只能包含整数,浮点数,操作数和括号。

How can i generate regular expression to validate please help or suggest any other way to validate that string. 我如何生成正则表达式以进行验证,请帮助或提出任何其他验证该字符串的方法。

Using Perl/PCRE we could verify such simple arithmetic expressions with help of a pattern structured like: 使用Perl / PCRE,我们可以借助如下结构的模式来验证这种简单的算术表达式:

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

Where num and op defined as required. 其中numop根据需要定义。 For example: 例如:

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

Which would give us the following working expression: 这将为我们提供以下工作表达:

(?x)^ (?&expr) $

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

But such expressions could not be used with .NET regex as it does not support (recursive) suppatern calls (?&name) . 但是此类表达式不能与.NET正则表达式一起使用,因为它不支持(递归)后继调用(?&name) Instead .NET regex lib offers us its special feature: balancing groups . 而是.NET regex lib为我们提供了其特殊功能: 平衡组

With balancing groups we could rewrite the required recursive call used in pnum , and use a structure like this instead: 使用平衡组,我们可以重写pnum使用的必需的递归调用,并使用如下结构:

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

What we've done here is to allow any number of optional opening and closing paranthesis before and after every number, counting the total number of open parentheses (?<p> \\( ) , subtracting closing parentheses from that number (?<-p> \\) ) and at the end of the expression make sure that the number of open parentheses is 0 (?(p)(?!)) . 我们在这里所做的是在每个数字前后允许任意数量的可选打开和关闭括号,计算打开括号(?<p> \\( )的总数,从该数字减去关闭括号(?<-p> \\) )并在表达式的末尾确保开括号的数量为0 (?(p)(?!))

(I believe this is equivalent to the original structure, altho I haven't made any formal proof.) (我相信这等效于原始结构,不过我还没有提供任何正式的证据。)

Resulting in the following .NET pattern: 产生以下.NET模式:

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

C# Example : 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"));
            }
        }
    }
}

Output: 输出:

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

You could write a simple lexer in F# using fslex/fsyacc. 您可以使用fslex / fsyacc在F#中编写一个简单的词法分析器。 Here is an example which is very close to your requirement: http://blogs.msdn.com/b/chrsmith/archive/2008/01/18/fslex-sample.aspx 这是一个非常接近您的要求的示例: 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