The (?!@) negative look-ahead will make word match only if @ does not appear immediately after word:
word(?!@)
If you need to fail a match when a word is followed with a character/string somewhere to the right, you may use any of the three below
word(?!.*@) # Note this will require @ to be on the same line as word
(?s)word(?!.*@) # (except Ruby, where you need (?m)): This will check for @ anywhere...
word(?![\s\S]*@) # ... after word even if it is on the next line(s)
See demo
This regex matches word substring and (?!@) makes sure there is no @ right after it, and if it is there, the word is not returned as a match (i.e. the match fails).
From Regular-expressions.info:
Negative lookahead is indispensable if you want to match something not followed by something else. When explaining character classes, this tutorial explained why you cannot use a negated character class to match a
qnot followed by au. Negative lookahead provides the solution:q(?!u). The negative lookahead construct is the pair of parentheses, with the opening parenthesis followed by a question mark and an exclamation point.
And on Character classes page:
Answer from Wiktor Stribiżew on Stack OverflowIt is important to remember that a negated character class still must match a character.
q[^u]does not mean: "aqnot followed by au". It means: "aqfollowed by a character that is not au". It does not match theqin the stringIraq. It does match theqand the space after theqin Iraq is a country. Indeed: the space becomes part of the overall match, because it is the "character that is not au" that is matched by the negated character class in the above regexp. If you want the regex to match theq, and only theq, in both strings, you need to use negative lookahead:q(?!u).
java - A regex to match a substring that isn't followed by a certain other substring - Stack Overflow
Regex match pattern not preceded by either of two expressions
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.
More on reddit.comregex - RegExp exclusion, looking for a word not followed by another - Stack Overflow
RegEx pattern with not followed by - Stack Overflow
Try:
/(?!.*bar)(?=.*foo)^(\w+)$/
Tests:
blahfooblah # pass
blahfooblahbarfail # fail
somethingfoo # pass
shouldbarfooshouldfail # fail
barfoofail # fail
Regular expression explanation
NODE EXPLANATION
--------------------------------------------------------------------------------
(?! look ahead to see if there is not:
--------------------------------------------------------------------------------
.* any character except \n (0 or more times
(matching the most amount possible))
--------------------------------------------------------------------------------
bar 'bar'
--------------------------------------------------------------------------------
) end of look-ahead
--------------------------------------------------------------------------------
(?= look ahead to see if there is:
--------------------------------------------------------------------------------
.* any character except \n (0 or more times
(matching the most amount possible))
--------------------------------------------------------------------------------
foo 'foo'
--------------------------------------------------------------------------------
) end of look-ahead
--------------------------------------------------------------------------------
^ the beginning of the string
--------------------------------------------------------------------------------
( group and capture to \1:
--------------------------------------------------------------------------------
\w+ word characters (a-z, A-Z, 0-9, _) (1 or
more times (matching the most amount
possible))
--------------------------------------------------------------------------------
) end of \1
--------------------------------------------------------------------------------
$ before an optional \n, and the end of the
string
Other regex
If you only want to exclude bar when it is directly after foo, you can use
/(?!.*foobar)(?=.*foo)^(\w+)$/
Edit
You made an update to your question to make it specific.
/(?=.*foo(?!bar))^(\w+)$/
New tests
fooshouldbarpass # pass
butnotfoobarfail # fail
fooshouldpassevenwithfoobar # pass
nofuuhere # fail
New explanation
(?=.*foo(?!bar)) ensures a foo is found but is not followed directly bar
To match a foo following by something that doesn't start with bar, try
foo(?!bar)
Your version with negative lookbehind is effectively "match a foo followed by something that doesn't end in bar". The .* matches all of barblah, and the (?<!bar) looks back at lah and checks that it doesn't match bar, which it doesn't, so the whole pattern matches.
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)
You don't say what flavor of regex you're using, but this should work in general:
Tom(?!\s+Thumb)
In case you are not looking for whole words, you can use the following regex:
Tom(?!.*Thumb)
If there are more words to check after a wanted match, you may use
Tom(?!.*(?:Thumb|Finger|more words here))
Tom(?!.*Thumb)(?!.*Finger)(?!.*more words here)
To make . match line breaks please refer to How do I match any character across multiple lines in a regular expression?
See this regex demo
If you are looking for whole words (i.e. a whole word Tom should only be matched if there is no whole word Thumb further to the right of it), use
\bTom\b(?!.*\bThumb\b)
See another regex demo
Note that:
\b- matches a leading/trailing word boundary(?!.*Thumb)- is a negative lookahead that fails the match if there are any 0+ characters (depending on the engine including/excluding linebreak symbols) followed withThumb.
Your regexp will match file paths which do not contain "Thumbnails" right before the file extension. You want to prevent it from matching those which contain "Thumbnails" anywhere in the text.
You could try something like:
<string>((?!.*Thumbnails).*?\.jpg)</string>
Or:
<string>((?![^<]*Thumbnails)[^<]*\.jpg)</string>
(That will prevent the regexp engine from going past the closing "<" when searching for "Thumbnails". It will also disallow file paths which contain "<".)
I presume you are matching this against individual lines of text, not against a string which contains multiple lines, right?
<string>^((?!Thumbnails).)*$</string>
You can search for any line matching either of the two lines, then only look at the last one:
grep "server crashed\|server is up again" | tail -n 1
or
# Use extended regular expressions, which treat | as an operator without escaping it
grep -E "server crashed|server is up again" | tail -n 1
or
# Use egrep, a synonym for grep -E
egrep "server crashed|server is up again" | tail -n 1
If the output contains "server crashed", you need to restart the server. If the output contains "server is up again", it is still running and you needn't do anything.
I like awk for simple state machines like this
awk '
/server crashed/ {is_crashed=1}
is_crashed && /server is up again/ {is_up_again=1; exit}
END {
if (! is_up_again) {
print "Oops, crashed and NOT up again"
exit 1
}
}
' filename
Answer from The fourth bird definitely works and it is well explained as well.
As an alternative to using word boundary one can use possessive quantifier i.e. ++ to turn off backtracking thus improving efficiency further.
\$this->\w++(?!\()
RegEx Demo
Please note use of \w instead of equivalent [a-zA-Z0-9_] here.
Like a greedy quantifier, a possessive quantifier repeats the token as many times as possible. Unlike a greedy quantifier, it does not give up matches as the engine backtracks.
The (?<!\() will always be true as the character class does not match a (
Note that you don't have to escape the \_
You can use a word boundary after the character class to prevent backtracking, and turn the negative lookbehind into a negative lookahead (?!\() to assert not ( directly to the right.
\$this->[a-zA-Z0-9_]+\b(?!\()
Regex demo

