Regex - how to match everything except a particular pattern
RegexFindstrRegex Problem Overview
How do I write a regex to match any string that doesn't meet a particular pattern? I'm faced with a situation where I have to match an (A and ~B) pattern.
Regex Solutions
Solution 1 - Regex
You could use a look-ahead assertion:
(?!999)\d{3}
This example matches three digits other than 999
.
But if you happen not to have a regular expression implementation with this feature (see Comparison of Regular Expression Flavors), you probably have to build a regular expression with the basic features on your own.
A compatible regular expression with basic syntax only would be:
[0-8]\d\d|\d[0-8]\d|\d\d[0-8]
This does also match any three digits sequence that is not 999
.
Solution 2 - Regex
If you want to match a word A in a string and not to match a word B. For example: If you have a text:
1. I have a two pets - dog and a cat
2. I have a pet - dog
If you want to search for lines of text that HAVE a dog for a pet and DOESN'T have cat you can use this regular expression:
^(?=.*?\bdog\b)((?!cat).)*$
It will find only second line:
2. I have a pet - dog
Solution 3 - Regex
Match against the pattern and use the host language to invert the boolean result of the match. This will be much more legible and maintainable.
Solution 4 - Regex
notnot, resurrecting this ancient question because it had a simple solution that wasn't mentioned. (Found your question while doing some research for a regex bounty quest.)
> I'm faced with a situation where I have to match an (A and ~B) > pattern.
The basic regex for this is frighteningly simple: B|(A)
You just ignore the overall matches and examine the Group 1 captures, which will contain A.
An example (with all the disclaimers about parsing html in regex): A is digits, B is digits within <a tag
The regex: <a.*?<\/a>|(\d+)
Demo (look at Group 1 in the lower right pane)
Reference
Solution 5 - Regex
The complement of a regular language is also a regular language, but to construct it you have to build the DFA for the regular language, and make any valid state change into an error. See this for an example. What the page doesn't say is that it converted /(ac|bd)/
into /(a[^c]?|b[^d]?|[^ab])/
. The conversion from a DFA back to a regular expression is not trivial. It is easier if you can use the regular expression unchanged and change the semantics in code, like suggested before.
Solution 6 - Regex
Solution 7 - Regex
(B)|(A)
then use what group 2 captures...
Solution 8 - Regex
My answer here might solve your problem as well:
https://stackoverflow.com/a/27967674/543814
- Instead of Replace, you would use Match.
- Instead of group
$1
, you would read group$2
. - Group
$2
was made non-capturing there, which you would avoid.
Example:
Regex.Match("50% of 50% is 25%", "(\d+\%)|(.+?)");
The first capturing group specifies the pattern that you wish to avoid. The last capturing group captures everything else. Simply read out that group, $2
.