4

I am trying to find a regular expression that will match a string when it's NOT preceded by another specific string (in my case, when it is NOT preceded by "http://"). This is in JavaScript, and I'm running on Chrome (not that it should matter).

The sample code is:

var str = 'http://www.stackoverflow.com www.stackoverflow.com';
alert(str.replace(new RegExp('SOMETHING','g'),'rocks'));

And I want to replace SOMETHING with a regular expression that means "match www.stackoverflow.com unless it's preceded by http://". The alert should then say "http://www.stackoverflow.com rocks", naturally.

Can anyone help? It feels like I tried everything found in previous answers, but nothing works. Thanks!

10
  • 1
    Read about "negative lookaheads". Commented Sep 18, 2013 at 23:59
  • Techically, this whole string is not preceded by http://; should it be replaced as a whole? Commented Sep 19, 2013 at 0:03
  • Uncaught SyntaxError: Invalid regular expression: /(?<!http:\/\/)www\.stackoverflow\.com/: Invalid group Commented Sep 19, 2013 at 0:03
  • 2
    JS regex engine doesn't support lookbehinds. Commented Sep 19, 2013 at 0:05
  • 1
    All I'm looking for is a RegEx that allows me to match string XXX if it's not preceded by YYY, in JavaScript. Commented Sep 19, 2013 at 0:09

3 Answers 3

4

As JavaScript regex engines don't support 'lookbehind' assertions, it's not possible to do with plain regex. Still, there's a workaround, involving replace callback function:

var str = "As http://JavaScript regex engines don't support `lookbehind`, it's not possible to do with plain regex. Still, there's a workaround";

var adjusted = str.replace(/\S+/g, function(match) {
  return match.slice(0, 7) === 'http://'
    ? match
    : 'rocks'
});
console.log(adjusted);

You can actually create a generator for these functions:

var replaceIfNotPrecededBy = function(notPrecededBy, replacement) {
   return function(match) {
     return match.slice(0, notPrecededBy.length) === notPrecededBy
       ? match
       : replacement;
   }
};

... then use it in that replace instead:

var adjusted = str.replace(/\S+/g, replaceIfNotPrecededBy('http://', 'rocks'));

JS Fiddle.

Sign up to request clarification or add additional context in comments.

Comments

0

raina77ow's answer reflected the situation in 2013, but it is now outdated, as the proposal for lookbehind assertions got accepted into the ECMAScript spec in 2018.

See docs for it on MDN:

Characters Meaning
(?<!y)x Negative lookbehind assertion: Matches "x" only if "x" is not preceded by "y". For example, /(?<!-)\d+/ matches a number only if it is not preceded by a minus sign. /(?<!-)\d+/.exec('3') matches "3". /(?<!-)\d+/.exec('-3') match is not found because the number is preceded by the minus sign.

Therefore, you can now express "match www.stackoverflow.com unless it's preceded by http://" as /(?<!http:\/\/)www.stackoverflow.com/:

const str = 'http://www.stackoverflow.com www.stackoverflow.com';
console.log(str.replace(/(?<!http:\/\/)www.stackoverflow.com/g, 'rocks'));

Comments

-1

This also works:

var variable = 'http://www.example.com www.example.com';
alert(variable.replace(new RegExp('([^(http:\/\/)|(https:\/\/)])(www.example.com)','g'),'$1rocks'));

The alert says "http://www.example.com rocks".

1 Comment

It works, but not in the way you think it does. Basically, as character class regex operator is used, you're just replacing a sequence of any symbol that's not in 'htps:/()|' range, followed by www.example.com. It'll give you a lot of false positives, first, and it's plain redundant, second.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.