我需要一个数学表达式的正则表达式,它应该满足我提出的这个SO Question中解释的以下条件。
这个表达式效果很好
但是现在我需要添加对左括号和右括号的支持以及以前的条件。所以我的正则表达式应该验证这些模式的表达式
例如。*6+(7-9)
或/6.25*(7-9.2)
或+6
或*6/(7.5-9)
我试图对现有的正则表达式进行修改,但没有成功。它还接受这些无效的模式,因为单括号可以出现在数学表达式中*6+(7-9
。*6+7-9)
这是链接RegExr。请帮忙。
我需要一个数学表达式的正则表达式,它应该满足我提出的这个SO Question中解释的以下条件。
这个表达式效果很好
但是现在我需要添加对左括号和右括号的支持以及以前的条件。所以我的正则表达式应该验证这些模式的表达式
例如。*6+(7-9)
或/6.25*(7-9.2)
或+6
或*6/(7.5-9)
我试图对现有的正则表达式进行修改,但没有成功。它还接受这些无效的模式,因为单括号可以出现在数学表达式中*6+(7-9
。*6+7-9)
这是链接RegExr。请帮忙。
@Bibhu,由于可以任意嵌套数学表达式,因此您需要一个实际的解析器来验证它们。正则表达式不起作用。正则表达式不足以处理任意深度的递归嵌套。
如果将嵌套限制在最大级别,则可以编写一个(非常大且丑陋的)正则表达式来验证表达式。但从根本上说,正则表达式是不适合这项工作的工具。
如果您有一个已经知道如何使用的解析器生成器,那将是为数学表达式构建解析器的最简单方法。如果你不这样做,手动编写一个简单的自顶向下递归下降解析器仍然很容易。
我想知道你是否提供赏金。
正则表达式中的简单递归是一个 gosub,其通过/失败返回恰好是可堆叠的。
下面是一个 Perl 例程,它为您指定的简单运算符和简单语法规则传递 Perl 自己的解析算法。它是在一个正则表达式中完成的,因为您的需求非常简单。
它看起来很花哨,但解析为“()”的简单平衡文本。看起来 Dot Net
可以做到这一点。只做替换应该很容易(即 (?&var) ),
平衡分组 Dot Net 需要......即时验证。
我发布这个是因为嵌套不是问题。问题在于,
解析看起来很简单,但魔鬼在细节中。
^
(?:
^ (?&sign)? (?&number)
|
(?&operator)
(?<! ^ (?:\/|\*) )
(?<! ^ [*]{2} )
(?&sign)? (?&number)
|
(?: (?&operator)
(?<! ^ (?:\/|\*) )
(?<! ^ [*]{2} )
(?<! [(] (?:\/|\*) )
(?<! [(] [*]{2} )
(?&sign)?
|
(?<= [(] )
|
^ (?&sign)?
)
(?<term>
\(
(?:
(?> (?&sign)?
(?&number)
(?: (?&operator) (?&sign)? (?&number) )*
)
|
(?>
(?: (?<= [(] ) | (?&operator) )
(?<! [(] (?:\/|\*) )
(?<! [(] [*]{2} )
(?&sign)?
(?&term)
)
)*
\)
(?! [(] )
(?> (?&operator) (?&sign)? (?&number) )*
)
)*
$
(?(DEFINE)
(?<number> \d+(?:\.\d+)? )
(?<sign> [+-] )
(?<operator>
(?: [*]{2}
| [\/*]
| (?<pm>[-+]) (?! \k<pm>) )
)
)
输出
passed ''
passed '(6**-2**3)'
passed '6-+2'
passed '-(-(8*((2)/3)))'
passed '-((8*((2)/3)))'
passed '-((8*((2**4)/3)))'
passed '-((8*((2**4)/3)))**((-1)*(8*((2**4/99)/3)))'
passed '-((8*((2**4)/3)))**((-1)*(8*((2**-4/99)/3)))'
passed '-((8*((2**4)/3)))**-((-1)*(8*((2**-4/99)/3)))'
passed '((8*((2)/3)))'
passed '((8*((2)/3)))'
passed '+((8*((-2)/-3)))'
passed '8-6*2'
passed '-8-6*2'
passed '((8*((2-(8*(8+6)/2))/3))-7*2/234)+8/2*1'
passed '-(8*(8+6)/2)'
passed '(9*9/9)'
passed '(9*(9)/9*(9*(9)/9)*1)'
passed '(9*(9)/9*(9*(9)/9))*(9*(9)/9*(9*(9)/9))'
failed '(6--2)'
failed '-(/(8*((2)/3)))'
failed '-((8*((2(6))/3)))'
failed '+((8*((+2)/--3)))'
failed '+((8*((+2)/--3+)))'
failed '+((8*((*2)/--3)))'
failed '+((8*((*2)/-3)))'
failed '-((8*((-2)/+-3)))'
failed '+8/2(1)'
failed '-(8)*(8/('
failed '-(8)*(8/()'
failed '*(9*9/9)'
failed '*(9*(9)/9*(9*(9)/9))*(9*(9)/9*(9*(9)/9))'
failed '/(9*(9)/9*(9*(9)/9))*(9*(9)/9*(9*(9)/9))'