rx-to-string
is an alternate concrete syntax for regular expressions. It translates its argument to a regular expression piece by piece. There is no negation operator in regular expressions, so there is no general negation operator in rx-to-string
either. The not
operator only recognizes a few specific constructs; for example, character sets can be negated easily, e.g. [abcdef]
to [^abcdef]
and vice versa, so rx supports not
on character sets. Similarly \sX
can be negated to \SX
, \b
to \B
, etc.
In principle, it would be possible to implement not
, since the complement of the language recognized by a regular expression can also be recognized by a regular expression. However, this requires a complete structural change in the regular expression, and in general the size of the regular expression for the negation is exponential in size compared to the original expression, so this may require a very long calculation and a large amount of memory, in addition to the coding effort. This is why regular expression engines don't provide negation, or only a restricted form of it (e.g. Perl's negative lookahead and lookbehind assertions).
The usual workaround when you need to negate something is to put the part you want to match in a group, and use code to analyze the matched group afterwards.
(if (string-match "stuff and \\(.*\\) and more" mystring)
(let ((could-be-anything (match-group 1)))
(if (not (save-match-data (string-match "not this" mystring))
…)))