Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Regular Expression Opposite

Tags:

regex

Is it possible to write a regex that returns the converse of a desired result? Regexes are usually inclusive - finding matches. I want to be able to transform a regex into its opposite - asserting that there are no matches. Is this possible? If so, how?

http://zijab.blogspot.com/2008/09/finding-opposite-of-regular-expression.html states that you should bracket your regex with

/^((?!^ MYREGEX ).)*$/ 

, but this doesn't seem to work. If I have regex

/[a|b]./ 

, the string "abc" returns false with both my regex and the converse suggested by zijab,

/^((?!^[a|b].).)*$/ 

. Is it possible to write a regex's converse, or am I thinking incorrectly?

like image 566
Greg Avatar asked May 12 '09 02:05

Greg


People also ask

How do you reverse a regular expression?

Another way to show that reverse(L) is regular is via regular expressions. For any regular expression r you can construct a regular expression r such that L(r ) = reverse(L) using the inductive definition of regular languages.

What is ?! In regex?

The ?! n quantifier matches any string that is not followed by a specific string n.

What is difference between regex and regular expression?

Since “regular expressions” is a mouthful, you will usually find the term abbreviated as “regex” or “regexp”. We prefer “regex”, since it can be easily pluralized as “regexes”.


2 Answers

Couldn't you just check to see if there are no matches? I don't know what language you are using, but how about this pseudocode?

if (!'Some String'.match(someRegularExpression))     // do something... 

If you can only change the regex, then the one you got from your link should work:

/^((?!REGULAR_EXPRESSION_HERE).)*$/ 
like image 101
Sasha Chedygov Avatar answered Sep 21 '22 02:09

Sasha Chedygov


The reason your inverted regex isn't working is because of the '^' inside the negative lookahead:

/^((?!^[ab].).)*$/       ^            # WRONG 

Maybe it's different in vim, but in every regex flavor I'm familiar with, the caret matches the beginning of the string (or the beginning of a line in multiline mode). But I think that was just a typo in the blog entry.

You also need to take into account the semantics of the regex tool you're using. For example, in Perl, this is true:

"abc" =~ /[ab]./ 

But in Java, this isn't:

"abc".matches("[ab].") 

That's because the regex passed to the matches() method is implicitly anchored at both ends (i.e., /^[ab].$/).

Taking the more common, Perl semantics, /[ab]./ means the target string contains a sequence consisting of an 'a' or 'b' followed by at least one (non-line separator) character. In other words, at ANY point, the condition is TRUE. The inverse of that statement is, at EVERY point the condition is FALSE. That means, before you consume each character, you perform a negative lookahead to confirm that the character isn't the beginning of a matching sequence:

(?![ab].). 

And you have to examine every character, so the regex has to be anchored at both ends:

/^(?:(?![ab].).)*$/ 

That's the general idea, but I don't think it's possible to invert every regex--not when the original regexes can include positive and negative lookarounds, reluctant and possessive quantifiers, and who-knows-what.

like image 23
Alan Moore Avatar answered Sep 17 '22 02:09

Alan Moore