regex that matches simple arithmetic expressions
Question:
i have a solution, but the only problem is that for example "7=7=7" is matched and that should not be the case.
^[+-]?d+([/*+-]d+)*([/*+-]*=(?:[+-]?d+([/*+-]d+)*)+)*$
see below of what is matched and not
these are matched and that is correct
456+5
0
0+0
5=0
1589+232
55+2
5+55
545454545
-12*53+1-2/5
+1+2+3=-5*2/3
000=0
18=+17/25
0-0
0*0
0/0
1/1
5/5
6*6
55/55
1/22
+55
5+5+5+5+5+5+5+5+5+5+5+5+5+5+5+5+5+5*5*5*5/5/5/5*5*5*5=5*5*5*5*5*5*5*5*5*5*5*5*5*5/5+5/5-6/5555/6
0*0*0*0*0*0*0+0=00000000*0*0
003+3*2
these shouldnt be matched which all of them except "7=7=7" does.
0=
5654*45=
*23
55++55
55+
7=7=7
18/-35
5*x
3.14159265358
how can i fix that the equal sign can only be there once, while also having a must that if a equal sign is there then there has to be a number after that
the answer must a regex
Answers:
You could replace the final *
with ?
: that way it can only occur once at the most:
^[+-]?d+([/*+-]d+)*([/*+-]*=(?:[+-]?d+([/*+-]d+)*)+)?$
Be aware that your regex also allows this:
1+1++++++++=1
That doesn’t seem right. I’m not sure why you have that [/*+-]*
sitting before =
.
You could avoid some repetition by using a negative look ahead assertion:
^(?!.*=.*=)[+-]?d+(([/*+-]|=[+-]?)d+)*$
You can match the follow regular expression.
^(?:[+-]?(?:d+[+/*-])*d+=)?[+-]?(?:d+[+/*-])*d+$
This does not match any string that contains more than one equals sign.
^ match the beginning of the string
(?: begin a non-capture group (A)
[+-]? optionally match one of the two characters in the character class
(?: begin a non-capture group (B)
d+ match one or more digits
[+/*-] match one of the four characters in the character class
) end non-capture group B
* execute non-capture group B zero or more times
d+ match one or more digits
= match '='
) end non-capture group A
? optionally match non-capture group A
[+-]? optionally match one of the two characters in the character class
(?: begin a non-capture group (C)
d+ match one or more digits
[+/*-] match one of the four characters in the character class
) end non-capture group C
* execute non-capture group C zero or more times
d+ match one or more digits
$ match end of the string
If you were to use Python’s alternative regex engine (import regex
) you could make use of the fact that it supports subroutines (a.k.a "subexpressions"):
^(?:([+-]?(?:d+[+/*-])*d+)=)?(?1)$
(?1)
causes itself to be replaced by the directives that match and save to capture group 1 (([+-]?(?:d+[+/*-])*d+)
). Not only does that reduce the size of the expression, it reduces the chance of errors being introduced.
i have a solution, but the only problem is that for example "7=7=7" is matched and that should not be the case.
^[+-]?d+([/*+-]d+)*([/*+-]*=(?:[+-]?d+([/*+-]d+)*)+)*$
see below of what is matched and not
these are matched and that is correct
456+5
0
0+0
5=0
1589+232
55+2
5+55
545454545
-12*53+1-2/5
+1+2+3=-5*2/3
000=0
18=+17/25
0-0
0*0
0/0
1/1
5/5
6*6
55/55
1/22
+55
5+5+5+5+5+5+5+5+5+5+5+5+5+5+5+5+5+5*5*5*5/5/5/5*5*5*5=5*5*5*5*5*5*5*5*5*5*5*5*5*5/5+5/5-6/5555/6
0*0*0*0*0*0*0+0=00000000*0*0
003+3*2
these shouldnt be matched which all of them except "7=7=7" does.
0=
5654*45=
*23
55++55
55+
7=7=7
18/-35
5*x
3.14159265358
how can i fix that the equal sign can only be there once, while also having a must that if a equal sign is there then there has to be a number after that
the answer must a regex
You could replace the final *
with ?
: that way it can only occur once at the most:
^[+-]?d+([/*+-]d+)*([/*+-]*=(?:[+-]?d+([/*+-]d+)*)+)?$
Be aware that your regex also allows this:
1+1++++++++=1
That doesn’t seem right. I’m not sure why you have that [/*+-]*
sitting before =
.
You could avoid some repetition by using a negative look ahead assertion:
^(?!.*=.*=)[+-]?d+(([/*+-]|=[+-]?)d+)*$
You can match the follow regular expression.
^(?:[+-]?(?:d+[+/*-])*d+=)?[+-]?(?:d+[+/*-])*d+$
This does not match any string that contains more than one equals sign.
^ match the beginning of the string
(?: begin a non-capture group (A)
[+-]? optionally match one of the two characters in the character class
(?: begin a non-capture group (B)
d+ match one or more digits
[+/*-] match one of the four characters in the character class
) end non-capture group B
* execute non-capture group B zero or more times
d+ match one or more digits
= match '='
) end non-capture group A
? optionally match non-capture group A
[+-]? optionally match one of the two characters in the character class
(?: begin a non-capture group (C)
d+ match one or more digits
[+/*-] match one of the four characters in the character class
) end non-capture group C
* execute non-capture group C zero or more times
d+ match one or more digits
$ match end of the string
If you were to use Python’s alternative regex engine (import regex
) you could make use of the fact that it supports subroutines (a.k.a "subexpressions"):
^(?:([+-]?(?:d+[+/*-])*d+)=)?(?1)$
(?1)
causes itself to be replaced by the directives that match and save to capture group 1 (([+-]?(?:d+[+/*-])*d+)
). Not only does that reduce the size of the expression, it reduces the chance of errors being introduced.