【正则表达式】匹配数字或四则运算的正则表达式

您所在的位置:网站首页 正则表达式匹配空格和加号 【正则表达式】匹配数字或四则运算的正则表达式

【正则表达式】匹配数字或四则运算的正则表达式

2024-06-01 01:04| 来源: 网络整理| 查看: 265

工作中遇到个需求,要验证用户输入的字符串是否为数字或四则运算式,过程中遇上了几个坑,虽然最后也没能完全解决这个问题,不过总算是有了个能用的正则表达式。

^(\-?\d+[\.\+\-\*\/]?)*\-?\d+$

该正则表达式:

可以匹配数字,正数负数小数皆可。 可以匹配数字,小数点以及 + - * / 组成的四则运算。 不支持优先级,即不支持括号 ()。 不支持带正号的正数出现在表达式开头,即不支持 +1 这种正数作为四则运算的开头。

不支持优先级这个问题比较难解决,因为正则表达式是有穷自动机,带优先级的四则运算是上下文无关语法,等价于非确定性下推自动机,正则表达式解决不了这个问题,外加个人能力限制,所以只能用在匹配时替换掉括号的临时方案代替。

正则表达式平衡组可以确定括号是否成对出现,使用此表达式即可 ^((?\()|(?\))|[^()]+)*(?(open)(?!))$ 但是无法确定括号出现的位置。

不支持带正号的数字开头则是可以解决的,将开头第三个字起的 \-? 换成 [\+\-]? 即可。

构建过程 首先是 正整数匹配

正整数匹配是最简单的,\d可以匹配数字,正整数是1个或多个数字重复,用+匹配,可得:

\d+ 然后是 增加负整数的匹配

负整数和正整数的区别就是负号,负号的出现的次数只会是负整数1次,正整数0次,用?匹配,可得:

\-?\d+ 第三步 增加小数点的匹配

小数点也同样有两种情况,整数时出现0次,小数时出现1次,小数的小数点后跟数字重复1次或更多次,可得:

\-?\d+(\.\d+)? 第四步 增加四则运算的开头

四则混合运算,会有括号或数字开头两种情况,数字会有正负整数或小数开头的四种情况,但不考虑括号,并且已经在第三步得到了匹配任何数字的表达式的情况下,四则运算只会以数字开头,所以直接:

^\-?\d+(\.\d+)? 第五步 增加减乘除符号

加减乘除只会跟在数字后面,并且只会出现一次,可得:

^\-?d+(\.\d+)?[\+\-\*\/] 第六步 增加四则运算的结尾

不考虑括号的情况下,四则运算的结尾同开头,只会出现数字,所以:

^\-?d+(\.\d+)?[\+\-\*\/]\-?\d+(\.\d+)?$ 第七步 增加四则运算的中间部分

第六步得到的正则表达式只能匹配两个数字之间的加减乘除,而四则运算是多个数字之间的加减乘除,这一步需要解决这个问题。

首先随手写出几个不带括号的四则运算式:

-10+5-3.6*4/8.5

8*1/4+-45+8*21

2--8*5.5/-7

分离开头的数字带符号,以及末尾的数字:

仔细观察可以得出以下规律:四则运算的中间部分,也是以数字后接运算符号的一个个节点组成的,如下:

中间的数字后接运算符号节点,可以用第五步的表达式,去掉匹配开头的 ^符号,即 \-?d+(\.\d+)?[+\-\*/] 来匹配,以为数字接符号节点,并且这个节点重复0次或任意次,可得:

^\-?d+(\.\d+)?[\+\-\*\/](\-?d+(\.\d+)?[\+\-\*\/])*\-?\d+(\.\d+)?$ 第八步 优化重复部分

第七步中的表达式有明显重复的部分,作为程序员看到重复就会想到这部分可以优化一下,而 XX* 形式的正则表达式,在正则中可以用 X+ 来代替,可得:

^(\-?d+(\.\d+)?+[\+\-\*\/])+\-?\d+(\.\d+)?$

不过这个表达式,可以匹配四则运算表达式但不能匹配数字了,而这二者之间的区别,在于数字接符号的节点出现0次还是出现更多次,即正则符号的 * ,故只需要将数字接符号的节点后的 +,替换为 * 就可以了:

^(\-?d+(\.\d+)?[\+\-\*\/])*\-?\d+(\.\d+)?$ 最后一步 优化小数点的部分

第八步中得到的表达式,已经可以作为匹配数字或四则运算的正则表达式了,不过在观察四则运算式的时候,我还发现,小数点,和加减乘除出现的地方其实是一致的,如下:

-10+    5- 3.    6*    -4/    8.    5

8*    1/    4+    -45+    8*    21

2-    -8* 5.    5/    -7

带或不带负号的数字,后接小数点或加减乘除,就组成了节点,节点重复任意次。

这样的话,将小数点视为加减乘除的同位,对表达式再次进行简化,可得:

^(\-?\d+[\.\+\-\*\/]?)*\-?\d+$

这样就得到开始的正则表达式了。

总结

没啥好总结的,不过这个过程真有趣。

总结记录一下,以后可能用的到。

以后也许会试试把括号的问题解决了。

补充: 正则表达式平衡组可以确定括号是否成对出现,使用此表达式即可 ^((?\()|(?\))|[^()]+)*(?(open)(?!))$ 但是无法确定括号出现的位置。



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3