You want to use negative lookbehind like this:
\w*(?<!foo)bar
Where (?<!x) means "only if it doesn't have "x" before this point".
See Regular Expressions - Lookaround for more information.
Edit: added the \w* to capture the characters before (e.g. "beach").
You want to use negative lookbehind like this:
\w*(?<!foo)bar
Where (?<!x) means "only if it doesn't have "x" before this point".
See Regular Expressions - Lookaround for more information.
Edit: added the \w* to capture the characters before (e.g. "beach").
Another option is to first match optional word characters followed by bar, and when that has matched check what is directly to the left is not foobar.
The lookbehind assertion will run after matching bar first.
\w*bar(?<!foobar)
\w*Match 0+ word charactersbarMatch literally(?<!foobar)Negative lookbehind, assert from the current positionfoobaris not directly to the left.
Regex demo
I'm a RegEx Noob and I'm using the regex (i.e. not re, for all that matters) to match a string not preceded by either of two expression.
So the regex should not match
foo bar baz bar
but should match bar in
blub bar
I know how to match a string not preceded by something. That would be:
(?<!foo )bar
But I can't use
(?<!foo|baz )bar
because Python doesn't support variable width lookbehinds. From StackOverflow I learned that I could invert my string and and use a negative lookahead, but isn't there a less weird solution in my case?
oof(?! rab| zad)
Are they actually the same length as foo and bar are - because it should work in that case.
>>> import re
>>> text = 'foo bar\nbaz bar\nblub bar'
>>> re.findall('\S+(?<!foo|baz) bar', text)
['blub bar']
The 3rd party regex module does support variable length (among other things)
>>> import regex as re
>>> re.findall('\S+(?<!foo|blub) bar', text)
['baz bar']
Alternative you could just capture all the matches and do the filtering yourself in code.
in addition to excellent points made by commandlineluser, you can use multiple look-behinds with re module when variable-length is required... for ex: re.search(r'(?<!foo)(?<!bigwordhere)bar', s) would be same as regex.search(r'(?<!foo|bigwordhere)bar', s)
regex - Match only if not preceded or followed by a digit - Stack Overflow
regular expression - Match one regex pattern if not preceded by another one - Vi and Vim Stack Exchange
Regex match exact word not preceded or followed by other characters
Not preceded by either or
Use .replace() for fun and profit
/(?:^|\s)(american tea)/ig
https://regex101.com/r/qB0uO2/1
if you want to account for prefixes AND suffixes:
/(?:^|\s)(american tea)(?:\W|$)/ig
https://regex101.com/r/qB0uO2/2
JSBIN EXAMPLE
var str = "American Tea is awesome. Do you like American Tea? love WowAmerican Tea #American Tea";
str.replace(/(?:^|\s)(american tea)(?:\W|$)/ig, function(i, m){
console.log(m);
});
//"American Tea"
//"American Tea"
EDIT:
The above returns only the matches, if instead you want to preserve the capturing and matching prefixes and suffixes use capturing-groups for them aswell:
var str = "American Tea is awesome. Do you like American Tea? love WowAmerican Tea #American Tea";
var newStr = str.replace(/(^|\s)(american tea)(\W|$)/ig, function(im, p1, p2, p3){
return p1 +"<b>"+ p2 +"</b>"+ p3; // p1 and p3 will help preserve the pref/suffix
});
document.getElementById("result").innerHTML = newStr;
<div id="result"></div>
where the parts
p1is the first matching group (any prefix)p2is the second matching group (the "American Tea" word)p3is the third matching group (any suffix)
You don't need regexes to match words.
I know a very neat CoffeeScript snippet :
wordList = ["coffeescript", "eko", "talking", "play framework", "and stuff", "falsy"]
tweet = "This is an example tweet talking about javascript and stuff."
wordList.some (word) -> ~tweet.indexOf word # returns true
Which compiles into the following javascript :
var tweet, wordList;
wordList = ["coffeescript", "eko", "talking", "play framework", "and stuff", "falsy"];
tweet = "This is an example tweet talking about javascript and stuff.";
wordList.some(function(word) { // returns true
return ~tweet.indexOf(word);
});
~ is not a special operator in CoffeeScript, just a cool trick. It is the bitwise NOT operator, which inverts the bits of its operand. In practice it equates to -x-1. Here it works on the basis that we want to check for an index greater than -1, and -(-1)-1 == 0 evaluates to false.
If you want the words that are matched, use :
wordList.filter (word) -> ~tweet.indexOf word # returns : [ "talking", "and stuff" ]
Or the same in JS :
wordList.filter(function(word) { // returns : [ "talking", "and stuff" ]
return ~tweet.indexOf(word);
});
This could be solved using a regular expression with negative lookbehind (which is experimentally supported in grep as pointed out by the comment from arrange):
$ grep -P '(?<!Mr )John Smith' file
Since the support is just experimental, you might want to use perl instead:
$ perl -nle 'print if /(?<!Mr )John Smith/' file
You can execute
command | grep 'John Smith' | grep -v 'Mr John Smith'
I'm a RegEx Noob and I'm using Python to match a string not preceded by either of two expression.
So the regex should not match
foo bar baz bar
but should match bar in
blub bar
I know how to match a string not preceded by something. That would be:
(?<!foo )bar
But I can't use
(?<!foo|baz )bar
because Python doesn't support variable width lookbehinds. From StackOverflow I learned that I could invert my string and and use a negative lookahead, but isn't there a less weird solution in my case?
oof(?! rab| zad)
Try this:
(?<=[ (])\w(?=[ )])
See it here in action: http://regexr.com?2vnri
Actually, this might be what you are looking for:
(?<= )\w+(?=[ )])|(?<=\()\w+(?=\))
See it here in action: http://regexr.com?2vnro
/(?<! [(\w] (?! \w+ \) ) ) \w+/x
or
/(?<! [(\w] ) \w+ | (?<= \( ) \w+ (?= \) )/x
You can use lookarounds:
(?<![A-Za-z0-9])Dd
Which means match d or D which is not preceded or followed by [A-Za-z0-9].
RegEx Demo
You're probably looking for word boundary anchors:
\bd\b
matches d only if it isn't adjacent to other alphanumerics.
Note that the definition of "alphanumeric" varies between regex engines. Most define them as the character set [A-Za-z0-9_], but some also include non-ASCII letters/digits.

