1

I've looked through numerous other questions up here surrounding a negative lookbehind for JavaScript but I can't seem to mimic them. I have the following Regex:

\b((?:http[s])?\S+\.\S+\.(?:\S+\.?){1,4})(?<!@)\b` 

and the basis of this Regex is it matches web addresses like:

  • www.msn.com
  • or http://www.msn.com
  • or https://www.google.com
  • or http://msdn.microsoft.com.

However, it also matches name@d1.d2.d3.d4 because of the numerous domain names following the @ sign. I need to perform a negative lookbehind for that @ sign.

Hopefully somebody can give me a hand!

UPDATE

Updating to include the replacement string that I'm using to create the hyperlink out of the matched text.

replace(webLinkPattern, "<a href=\"http://$2\" target=\"_blank\" onclick=\"preventDualEditing(event)\">$2</a>");

UPDATE 2 - ANSWER

ts = ts.replace(webLinkPattern, function (url) {
    if (url.indexOf('@') != -1) {
        return url;
    }

    return url.replace(webLinkPattern, "<a href=\"http://$&\" target=\"_blank\" onclick=\"preventDualEditing(event)\">$&</a>");
});
Mike Perrenoud
  • 66,820
  • 29
  • 157
  • 232
  • Do you want it to match the entire e-mail, or just the domain portion of the e-mail? – Jordan Mack Mar 19 '12 at 23:48
  • I don't want it to match the email at all - I have another Regex that matches the email addresses. See, I have to take the result and turn it into a link so I need to make sure I'm not picking up email addresses. – Mike Perrenoud Mar 19 '12 at 23:52
  • instead of using `\S`, why not limit your set to valid characters using `[]` – Joseph Mar 19 '12 at 23:53
  • @Joseph That's a pretty long list of characters for web addresses isn't it? – Mike Perrenoud Mar 19 '12 at 23:54
  • @mperrenoud03 you can use ranges like `[A-Za-z0-9]` for alphanumeric – Joseph Mar 19 '12 at 23:57
  • @Joseph the problem with that however is that it will match everything after the `@` in those email addresses. – Mike Perrenoud Mar 20 '12 at 00:03
  • 1
    See also [Javascript: negative lookbehind equivalent?](https://stackoverflow.com/questions/641407/javascript-negative-lookbehind-equivalent) as well as this [more comprehensive answer](https://stackoverflow.com/questions/35142364/regex-negative-lookbehind-not-valid-in-javascript/35143111#35143111 "regex Negative Lookbehind not valid in javascript") with full descriptions of how to match and replace with both positive and negative lookbehinds. This is a duplicate of those questions. – Adam Katz Feb 09 '16 at 01:54

1 Answers1

2

JavaScript doesn't support lookbehind assertions, so you'll have to handle this in your own code. One option is simply to include the @ in the result, and then discard the match if the @ is there:

replace(/(?:\b|@)(?:https?)?\S+\.\S+\.(?:\S+\.?){1,4}\b/,
        function(url) {
          if(url.indexOf('@') > -1)
            return url;
          return '<a href="' + url + ' target="_blank"' +
                 ' onclick="preventDualEditing(event)">' + url + '</a>';
        }
       );

Alternatively, you can check for a preceding @ in the callback, even without including it in url:

replace(/\b(?:https?)?\S+\.\S+\.(?:\S+\.?){1,4}\b/,
        function(url, pos, str) {
          if(pos > 0 && str.charAt(pos - 1) == '@')
            return url;
          return '<a href="' + url + ' target="_blank"' +
                 ' onclick="preventDualEditing(event)">' + url + '</a>';
        }
       );

(Note that I've also changed http[s] to https?, which is what you meant. http[s] is the same as https, since [s] is a character class matching any character that's s.)

ruakh
  • 175,680
  • 26
  • 273
  • 307
  • I don't think this will work in my situation because I need to create a real link out of it during a REPLACE - so I need to make sure I'm not matching email address. – Mike Perrenoud Mar 19 '12 at 23:53
  • 1
    @mperrenoud03: You can use a callback instead of a simple string as your replacement. If you post your replacement-string, I'll update my answer with a callback you can use. – ruakh Mar 19 '12 at 23:54
  • I updated the question with the exact answer that worked for me - but your direction got me there. – Mike Perrenoud Mar 20 '12 at 01:07