3

I am trying to have a regular expression split on equations like 1.5+4.2*(5+2) with operators - + * / so the output would be input into a array so I can parse individually

[0]1.5 [1]+ [2]4.2 [3]* [4]( [5]5 [6]+ [7]2 [8]) 

I have found out that the \b will work on 1+2+3 however if I were to have decimal points it would not split.

I have tried splitting with \b(\.\d{1,2}) however it does not split on the decimal point

2
  • I'm curious as to what you plan to do when you have the different pieces. Could this be another instance where you want to lexically analyze a grammar (lex/yacc), rather than run it through a regex? Commented Jul 30, 2010 at 18:52
  • I know it isn't my place to alter the title because of a pet peace of mine, but the fact that some people say "maths" instead of "math" bugs me. Commented Mar 18, 2014 at 3:01

4 Answers 4

18

You can use zero-width matching lookahead and lookbehind combo as alternates.

String equation = "1.5+4.2*(5+2)"; String regex = "(?<=op)|(?=op)".replace("op", "[-+*/()]"); // actual regex becomes (?<=[-+*/()])|(?=[-+*/()]) System.out.println(java.util.Arrays.toString( equation.split(regex) )); // ___ _ ___ _ _ _ _ _ _ // [1.5, +, 4.2, *, (, 5, +, 2, )] 

Explanation

  • […] is a character class definition
  • (?<=…) is a lookbehind; it asserts that we can match to the left
  • (?=…) is a lookahead; it asserts that we can match to the right
  • this|that is alternation
  • Thus, (?<=op)|(?=op) matches everywhere after or before op
    • ... where op is replaced by [-+*/()], i.e. a character class that matches operators
      • Note that - is first here so that it doesn't become a range definition meta character

References

Related questions


More examples of zero-width matching regex for splitting

Here are more examples of splitting on zero-width matching constructs; this can be used to split a string but also keep delimiters.

Simple sentence splitting, keeping punctuation marks:

String str = "Really?Wow!This.Is.Awesome!"; System.out.println(java.util.Arrays.toString( str.split("(?<=[.!?])") )); // prints "[Really?, Wow!, This., Is., Awesome!]" 

Splitting a long string into fixed-length parts, using \G

String str = "012345678901234567890"; System.out.println(java.util.Arrays.toString( str.split("(?<=\\G.{4})") )); // prints "[0123, 4567, 8901, 2345, 6789, 0]" 

Split before capital letters (except the first!)

System.out.println(java.util.Arrays.toString( "OhMyGod".split("(?=(?!^)[A-Z])") )); // prints "[Oh, My, God]" 

A variety of examples is provided in related questions below.

Related questions

Sign up to request clarification or add additional context in comments.

1 Comment

Great post, but I was wondering: how would one avoid splitting negative numbers?
6
Pattern pattern = Pattern.compile("((\\d*\\.\\d+)|(\\d+)|([\\+\\-\\*/\\(\\)]))"); Matcher m = pattern.matcher("1.5+4.2*(5+2)/10-4"); while(m.find()) { System.out.printf("%s ", m.group()); } output: 1.5 + 4.2 * ( 5 + 2 ) / 10 - 4 

You can also use ?: to avoid capturing groups. I left it to make it simple.

Comments

3

Use match, instead of split:

(?:\d+\.)?\d*(?:e[+\-]?\d+)?|[\s\-\/()+*%=] 

This regex will also accept valid floats like: 1.2e+3 * 2 which should equal 2400. the regexes given by the other respondents will fail.

1 Comment

Would this work with negative numbers as well? How would you use it in Java in order to split your string?
0

Split the string using [+-/*()].

2 Comments

hi,however i also need to include the operators so i cant use the regex you given
Store the match via enclosing parentheses.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.