Search code examples
javascriptregexregex-lookaroundslookbehindnegative-lookbehind

Mimicking negative lookbehind to match a pattern not immediately preceded with a specific character in JavaScript regex


I have this regex in Javascript:

0x[A-F0-9]{2}\g

I would like to modify that in order to get a match when the previous character IS NOT a \. Something like that:

  • 0x60 -> true
  • \0x60 -> false

I came out with something like that but it's not working properly:

[^\\]0x[A-F0-9]{2}\g

It matches EVERYTHING except \, where by EVERYTHING i mean:

  • a0x50 -> true, including "a"
  • _0x50 -> true, including "_"
  • ...
  • \0x50 -> false

Regex example: regex101, followed by a Plnkr.

Is it possible to achieve that? Thanks.


Solution

  • The main point is to match the pattern you would normally put into a negative lookbehind into an optional capturing group, and then check if the group matched. If it did, you do not need the match, else, use it.

    If you need to match and collect substrings, use

    var re = /(\\?)0x[A-F0-9]{2}/gi; 
    var str = '\\0x50 0x60 asdasda0x60';
    var res = [];
    while ((m = re.exec(str)) !== null) {
    	if (!m[1]) {
      	res.push(m[0]); 
      }
    }
    document.body.innerHTML = "TEST: " + str + "<br/>";
    document.body.innerHTML += "RES: " + JSON.stringify(res,0,4) + "<br/>";

    If you need to replace only those strings that have no \ before the 0x.., use a callback within the replace method to check if Group 1 matched. If it did, replace with the whole match, and if not, just replace with the pattern you need.

    var re = /(\\?)0x[A-F0-9]{2}/gi; 
    var str = '\\0x50 0x60 asdasda0x60';
    var res = str.replace(re, function(m, group1){
    	return group1 ? m : "NEW_VAL";
    });
    document.body.innerHTML = "TEST: " + str + "<br/>";
    document.body.innerHTML += "RES: " + res + "<br/>";