0

I want to make a regex to match either of multiplication or division operation in mathematical equation which may contain power symbol (^). The match begin between the factor within the most brackets and its nearby variable. I have created my own regex but I faced two main problems:

  1. It doesn't match two factors that not contain * symbol between them (see example 2), I want it match.
  2. It match the operation that only contain - symbol (example 4), I want it doesn't except there is * or / symbol before - symbol (example 3).

Here are my experiments:

EXAMPLE 1

String:

(sdf^sdf*(sdf*(23^3s)))*sdf

Expected result:

(sdf*(23^3s))

My current result:

(sdf*(23^3s))

EXAMPLE 2

String

(232^23)dfdf+dfd(sfsf)

Expected Result

(232^23)dfdf

My current result:

(doesn't match at all)

EXAMPLE 3

String

dfd(sfsf^sdf+323)/-13+sfdfsdf

Expected Result (UPDATED)

dfd(sfsf^sdf+323)

My current result

(sfsf^sdf+323)/-13

EXAMPLE 4

String

(dfd^23sdf)-(234^dfd)

Expected Result

(doesn't match anything)

My current result

(dfd^23sdf)-(234^dfd)

EXAMPLE 5

String

(dfd^23sdf)-(234^dfd)*(x-3)

Expected Result

(234^dfd)*(x-3)

My current result

(dfd^23sdf)-(234^dfd)*(x-3)

Here is my regex:

(\-?)\(?(((\-?)\-?\d*\.?\d*[a-z]*\^?)+)\)?(\*?\/?)((\-?)\(([^\(\)]+)\))(\*?\/?)(\-?)\(?(((\-?)\-?\d*\.?\d*[a-z]*\^?)+)\)|(((\-?)\(([^\(\)]+)\))([\*\/])(\-?)(((?!\+)(\-?)\(?[\-\d\.\w\^\+\-\*\/]*\)?))?)
Kevin A.S.
  • 123
  • 7
  • Possible duplicate of [Regex lookahead, lookbehind and atomic groups](https://stackoverflow.com/questions/2973436/regex-lookahead-lookbehind-and-atomic-groups) – ArSeN Mar 16 '19 at 16:19
  • You lost me at what comes after "Here is my regex." Is there some reason why you can't/don't want to just write a simple _parser_ to parse the arithmetic expression? A parser is how I would handle this problem. – Tim Biegeleisen Mar 16 '19 at 16:19
  • Recently I build a kind of algebra calculator. Using a parser is difficult to be synchronized with my own program. – Kevin A.S. Mar 16 '19 at 16:23
  • @ArSeN it maybe related to regex lookahead, lookbehind and atomic groups, but the question is how to apply that function to the OP's regex and solve his problem. If my question itsels contain something about regex, does it make my question a duplicate of another regex question too? – Kevin A.S. Mar 16 '19 at 16:31
  • This is not at all clear, please add the exact requirements for the pattern. – Wiktor Stribiżew Mar 16 '19 at 18:16
  • @WiktorStribiżew Sorry if it's not clear. I have updated my example 3 because the expected result is wrong. Anyway, I have found the solution. Thanks for your help willing. – Kevin A.S. Mar 16 '19 at 20:01
  • I spent some ten minutes and came up with the right regex for this, but did not keep it because your example was wrong. Next time, make sure you explain why you want this output and not another, it is even good as a self-check. – Wiktor Stribiżew Mar 16 '19 at 20:19
  • @WiktorStribiżew Yeah, thank you. Anyway, can I have a look for your regex? It might be much better than mine. – Kevin A.S. Mar 16 '19 at 20:21
  • Only if it still exists. – Kevin A.S. Mar 16 '19 at 20:24
  • There may be other examples this fails for, but you might be able to use something like [`(\w+|\([^()]+\))\*?(\([^()]+\))|(?2)\*?(?1)`](https://regex101.com/r/5Wm1Eb/5) - match word characters next to a `(` or `)`, optionally separated by a `*`, and make sure that the matched parentheses don't contain any other nested parentheses. – CertainPerformance Jul 02 '19 at 07:02
  • @CertainPerformance Your code is more simple than mine and also applicable. Tq – Kevin A.S. Jul 02 '19 at 07:05

2 Answers2

1

A suggestion. If you're happy with the regex you've got you can speed it up by making all the groups clusters then running it through regex refactor software here http://www.regexformat.com

Before:

https://regex101.com/r/5Wm1Eb/4

(\-?((\w+\.\^\(.*?\)|([\w\.\^]+))|(\(?\(([^\(\)]+)\)\)?))(((\/)(?!\-))|((\*)(?!\-))|(\/\-)|(\*\-))?\(([^\(\)]+)\))|(\-?\(([^\(\)]+)\)((((\/)(?!\-))|((\*)(?!\-))|(\/\-)|(\*\-))?((\w+\.\^\(.*?\)|([\w\.\^]+))|(\(?\(([^\(\)]+)\)\)?))))

After, twice as fast, half as big:

https://regex101.com/r/TbHlI1/1

\-?(?:(?:\w+\.\^\(.*?\)|[\w\.\^]+|\(?\([^\(\)]+\)\)?)(?:[*/](?:(?!\-)|\-))?\([^\(\)]+\)|\([^\(\)]+\)(?:[*/](?:(?!\-)|\-))?(?:\w+\.\^\(.*?\)|[\w\.\^]+|\(?\([^\(\)]+\)\)?))

enter image description here

sln
  • 2,071
  • 1
  • 3
  • 11
0

After few hours of finding solution, here is what I got:

I write down the regex to match operation like (*), (/), (*-), or (/-).

(((\/)(?!\-))|((\*)(?!\-))|(\/\-)|(\*\-))?

After that, I make a regex to find the factor within the most brackets and its closest back variable which match the condition.

(((\w+\^\(.*?\)|([\w\^]+))|(\(?\(([^\(\)]+)\)\)?))(((\/)(?!\-))|((\*)(?!\-))|(\/\-)|(\*\-))?\(([^\(\)]+)\))

If it doesn't match, then try again to find the factor within the most brackets and its closest front variable which match the condition.

(\(([^\(\)]+)\)((((\/)(?!\-))|((\*)(?!\-))|(\/\-)|(\*\-))?((\w+\^\(.*?\)|([\w\^]+))|(\(?\(([^\(\)]+)\)\)?))))

Then, combine those two regexs above using OR (|) quantifier to get the desired result.

DEMO

UPDATED

I modified some parts, so it can match negative factor and decimal (marked with '.' symbol).

DEMO

Kevin A.S.
  • 123
  • 7