While stribizhev's answer might work in most situations, it is not a true inversion of the regex in the question, as there are things that both regex'es don't match:
- Spaces
- Special characters like
?!^~;:_,.[]{}<> (and probably more).
And things that both regex'es do match:
- Strings such as
axabs(3), where the xabs part is matched by both.
This could probably be fixed by fiddling around, but hell, I want an actual inversion! :P
So here it is:
(?:(?!e|ln|(?<=l)n|pi|(?<=p)i|abs|(?<=a)bs|(?<=ab)s|pow|(?<=p)ow|(?<=po)w|sin|(?<=s)in|(?<=si)n|cos|(?<=c)os|(?<=co)s|tan|(?<=t)an|(?<=ta)n|asin|acos|atan)[^0-9-+*/()x])+
It works like this:
- Match any character that is not one of
0-9-+*/()x (= [^0-9-+*/()x]).
But do not match that character, if it matches a certain pattern of preceeding/following characters, and is itself a certain character.
Using a negative lookahead ((?!...)) means that the first character after every | is the current character, the characters after that are the ones following the current one, and the (?<=) is a negative lookbehind, matching certain preceding characters.
So, for example, in order to not match sin, we need to "not match" s if followed by in, not match i if preceded by s and followed by n and not match n if preceded by si.
In regex (lookaround part only): (?!sin|(?<=s)in|(?<=si)n)
Constructing the full list for e, ln, pi, etc. results in:
(?!e|ln|(?<=l)n|pi|(?<=p)i|abs|(?<=a)bs|(?<=ab)s|pow|(?<=p)ow|(?<=po)w|sin|(?<=s)in|(?<=si)n|cos|(?<=c)os|(?<=co)s|tan|(?<=t)an|(?<=ta)n|asin|acos|atan)
Match the above one or more times ((?:...)+).
By merging parts like (?<=l)n, (?<=si)n and (?<=ta)n into (?<=l|si|ta)n, the regex can be shortened a bit:
(?:(?!e|ln|(?<=l|si|ta)n|pi|(?<=p)i|abs|(?<=a)bs|(?<=ab|co)s|pow|(?<=p)ow|(?<=po)w|a?(?:sin|cos|tan)|(?<=s)in|(?<=c)os|(?<=t)an)[^0-9-+*/()x])+
A demo of this, as well as a beautiful visualization can be viewed on Debuggex.
Note 1: This regex does not work in JavaScript, as JS-regex does not support lookbehind.
Note 2: Appending a single multi-byte character (such as §°☀☁️❄️, for example) to the test string in Debuggex might seem to break it, however this is not an issue with my regex, as can be verified with PHP, for example.