Negative lookbehinds seem to be the only answer, but JavaScript doesn't has one. Consider posting the regex as it would look with a negative lookbehind; that may make it easier to respond. @WiktorStribiżew : Look-behinds were added in the 2018 spec. Chrome supports them, but Firefox still hasn't implemented the spec.
Lookbehind has the same effect, but works backwards. It tells the regex engine to temporarily step backwards in the string, to check if the text inside the lookbehind can be matched there. (? <!a)b matches a “b” that is not preceded by an “a”, using negative lookbehind.
JavaScript doesn't support any lookbehind, but it can support lookaheads.
The syntax is: X(?= Y) , it means "look for X , but match only if followed by Y ". There may be any pattern instead of X and Y . For an integer number followed by € , the regexp will be \d+(?=
EDIT: From ECMAScript 2018 onwards, lookbehind assertions (even unbounded) are supported natively.
In previous versions, you can do this:
^(?:(?!filename\.js$).)*\.js$
This does explicitly what the lookbehind expression is doing implicitly: check each character of the string if the lookbehind expression plus the regex after it will not match, and only then allow that character to match.
^ # Start of string
(?: # Try to match the following:
(?! # First assert that we can't match the following:
filename\.js # filename.js
$ # and end-of-string
) # End of negative lookahead
. # Match any character
)* # Repeat as needed
\.js # Match .js
$ # End of string
Another edit:
It pains me to say (especially since this answer has been upvoted so much) that there is a far easier way to accomplish this goal. There is no need to check the lookahead at every character:
^(?!.*filename\.js$).*\.js$
works just as well:
^ # Start of string
(?! # Assert that we can't match the following:
.* # any string,
filename\.js # followed by filename.js
$ # and end-of-string
) # End of negative lookahead
.* # Match any string
\.js # Match .js
$ # End of string
^(?!filename).+\.js
works for me
tested against:
A proper explanation for this regex can be found at Regular expression to match string not containing a word?
Look ahead is available since version 1.5 of javascript and is supported by all major browsers
Updated to match filename2.js and 2filename.js but not filename.js
(^(?!filename\.js$).).+\.js
Let's suppose you want to find all int
not preceded by unsigned
:
With support for negative look-behind:
(?<!unsigned )int
Without support for negative look-behind:
((?!unsigned ).{9}|^.{0,8})int
Basically idea is to grab n preceding characters and exclude match with negative look-ahead, but also match the cases where there's no preceeding n characters. (where n is length of look-behind).
So the regex in question:
(?<!filename)\.js$
would translate to:
((?!filename).{8}|^.{0,7})\.js$
You might need to play with capturing groups to find exact spot of the string that interests you or you want't to replace specific part with something else.
If you can look ahead but back, you could reverse the string first and then do a lookahead. Some more work will need to be done, of course.
This is an equivalent solution to Tim Pietzcker's answer (see also comments of same answer):
^(?!.*filename\.js$).*\.js$
It means, match *.js
except *filename.js
.
To get to this solution, you can check which patterns the negative lookbehind excludes, and then exclude exactly these patterns with a negative lookahead.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With