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.