Match everything except for specified strings
I know that the following regex will match "red", "green", or "blue".
red|green|blue
Is there a straightforward way of making it ma开发者_JAVA百科tch everything except several specified strings?
If you want to make sure that the string is neither red, green nor blue, caskey's answer is it. What is often wanted, however, is to make sure that the line does not contain red, green or blue anywhere in it. For that, anchor the regular expression with ^
and include .*
in the negative lookahead:
^(?!.*(red|green|blue))
Also, suppose that you want lines containing the word "engine" but without any of those colors:
^(?!.*(red|green|blue)).*engine
You might think you can factor the .*
to the head of the regular expression:
^.*(?!red|green|blue)engine # Does not work
but you cannot. You have to have both instances of .*
for it to work.
Depends on the language, but there are generally negative-assertions you can put in like so:
(?!red|green|blue)
(Thanks for the syntax fix, the above is valid Java and Perl, YMMV)
Matching Anything but Given Strings
If you want to match the entire string where you want to match everything but certain strings you can do it like this:
^(?!(red|green|blue)$).*$
This says, start the match from the beginning of the string where it cannot start and end with red, green, or blue and match anything else to the end of the string.
You can try it here: https://regex101.com/r/rMbYHz/2
Note that this only works with regex engines that support a negative lookahead.
You don't need negative lookahead. There is working example:
/([\s\S]*?)(red|green|blue|)/g
Description:
[\s\S]
- match any character*
- match from 0 to unlimited from previous group?
- match as less as possible(red|green|blue|)
- match one of this words or nothingg
- repeat pattern
Example:
whiteredwhiteredgreenbluewhiteredgreenbluewhiteredgreenbluewhiteredgreenbluewhiteredgreenbluewhiteredgreenbluewhiteredgreenbluewhiteredwhiteredwhiteredwhiteredwhiteredwhiteredgreenbluewhiteredwhiteredwhiteredwhiteredwhiteredredgreenredgreenredgreenredgreenredgreenbluewhiteredbluewhiteredbluewhiteredbluewhiteredbluewhiteredwhite
Will be:
whitewhitewhitewhitewhitewhitewhitewhitewhitewhitewhitewhitewhitewhitewhitewhitewhitewhitewhitewhitewhitewhitewhitewhitewhite
Test it: regex101.com
I had the same question, the solutions proposed were almost working but they had some issue. In the end the regex I used is:
^(?!red|green|blue).*
I tested it in Javascript and .NET.
.* should't be placed inside the negative lookahead like this: ^(?!.*red|green|blue) or it would make the first element behave different from the rest (i.e. "anotherred" wouldn't be matched while "anothergreen" would)
Matching any text but those matching a pattern is usually achieved with splitting the string with the regex pattern.
Examples:
- c# -
Regex.Split(text, @"red|green|blue")
or, to get rid of empty values,Regex.Split(text, @"red|green|blue").Where(x => !string.IsNullOrEmpty(x))
(see demo) - vb.net -
Regex.Split(text, "red|green|blue")
or, to remove empty items,Regex.Split(text, "red|green|blue").Where(Function(s) Not String.IsNullOrWhitespace(s))
(see demo, or this demo where LINQ is supported) - javascript -
text.split(/red|green|blue/)
(no need to useg
modifier here!) (to get rid of empty values, usetext.split(/red|green|blue/).filter(Boolean)
), see demo - java -
text.split("red|green|blue")
, or - to keep all trailing empty items - usetext.split("red|green|blue", -1)
, or to remove all empty items use more code to remove them (see demo) - groovy - Similar to Java,
text.split(/red|green|blue/)
, to get all trailing items usetext.split(/red|green|blue/, -1)
and to remove all empty items usetext.split(/red|green|blue/).findAll {it != ""})
(see demo) - kotlin -
text.split(Regex("red|green|blue"))
or, to remove blank items, usetext.split(Regex("red|green|blue")).filter{ !it.isBlank() }
, see demo - scala -
text.split("red|green|blue")
, or to keep all trailing empty items, usetext.split("red|green|blue", -1)
and to remove all empty items, usetext.split("red|green|blue").filter(_.nonEmpty)
(see demo) - ruby -
text.split(/red|green|blue/)
, to get rid of empty values use.split(/red|green|blue/).reject(&:empty?)
(and to get both leading and trailing empty items, use-1
as the second argument,.split(/red|green|blue/, -1)
) (see demo) - perl -
my @result1 = split /red|green|blue/, $text;
, or with all trailing empty items,my @result2 = split /red|green|blue/, $text, -1;
, or without any empty items,my @result3 = grep { /\S/ } split /red|green|blue/, $text;
(see demo) - php -
preg_split('~red|green|blue~', $text)
orpreg_split('~red|green|blue~', $text, -1, PREG_SPLIT_NO_EMPTY)
to output no empty items (see demo) - python -
re.split(r'red|green|blue', text)
or, to remove empty items,list(filter(None, re.split(r'red|green|blue', text)))
(see demo) - go - Use
regexp.MustCompile("red|green|blue").Split(text, -1)
, and if you need to remove empty items, use this code. See Go demo.
NOTE: If you patterns contain capturing groups, regex split functions/methods may behave differently, also depending on additional options. Please refer to the appropriate split method documentation then.
All except word "red"
var href = '(text-1) (red) (text-3) (text-4) (text-5)';
var test = href.replace(/\((\b(?!red\b)[\s\S]*?)\)/g, testF);
function testF(match, p1, p2, offset, str_full) {
p1 = "-"+p1+"-";
return p1;
}
console.log(test);
All except word "red"
var href = '(text-1) (frede) (text-3) (text-4) (text-5)';
var test = href.replace(/\(([\s\S]*?)\)/g, testF);
function testF(match, p1, p2, offset, str_full) {
p1 = p1.replace(/red/g, '');
p1 = "-"+p1+"-";
return p1;
}
console.log(test);
精彩评论