我有一个算术表达式
string exp = "((2+3.1)/2)*4.456";
我想通过使用正则表达式进行验证。表达式只能有整数,浮点数,操作数和括号。
如何生成正则表达式以验证请帮助或建议任何其他方式来验证该字符串。
答案 0 :(得分:7)
使用Perl / PCRE,我们可以借助如下结构的模式验证这些简单的算术表达式:
expr = pnum ( op pnum )*
pnum = num | \( expr \)
根据需要定义num
和op
的位置。例如:
num = -?+\d++(?:\.\d++)?+
op = [-+*/]
这会给我们以下工作表达式:
(?x)^ (?&expr) $
(?(DEFINE)
(?<expr> (?&pnum) (?: (?&op) (?&pnum) )*+ )
(?<pnum> (?> (?&num) | \( (?&expr) \) ) )
(?<num> -?+\d++(?:\.\d++)?+ )
(?<op> [-+*/] )
)
但是这样的表达式不能与.NET正则表达式一起使用,因为它不支持(递归)支持调用(?&name)
。
相反,.NET正则表达式lib为我们提供了它的特殊功能:balancing groups。
使用平衡组,我们可以重写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# Example 强>:
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
答案 1 :(得分:1)
您可以使用fslex / fsyacc在F#中编写一个简单的词法分析器。以下是一个非常接近您要求的示例:http://blogs.msdn.com/b/chrsmith/archive/2008/01/18/fslex-sample.aspx