2

I'm trying to create regexp matching <<merge_field>> and not matching href="<<merge_field>>

I've used negative lookbehind construct, but it doesn't work in IE11 and Safari. Is there any regexp solution?

Current expression is (?<!href=")[<]{2}((?:merge_field))[>]{2}

Spike_Doc
  • 33
  • 1
  • 5
  • 1
    There is _**NO JS ALTERNATIVE FOR LOOK BEHIND ASSERTIONS**_ Please understand that !!!! The only way to match something _bad_ is to move the match position past it. This requires matching the bad part as well as the good. –  Nov 13 '18 at 10:46
  • You can match both `(href=['"]<>)|(<>)` used in a replace callback. Return group 1 with itself. Return group 2 with the replacement, or with itself if just recording the position. –  Nov 13 '18 at 10:55
  • I've tried to do this way, but it replaces both $1 and $2. Did I do something wrong? const regexMergeFields = new RegExp('(href=\"<<' + mergeFields+ '>>)|<<(' + mergeFields+ ')>>', 'g'); return str.replace( regexMergeFields, this.wrapMergeField('$2') ); – Spike_Doc Nov 13 '18 at 12:53
  • Added an example. –  Nov 13 '18 at 17:21

1 Answers1

2

In a single regex, we match the part that would normally be skipped with a lookbehind asserrtionhref="<<merge_field>>
and also the part that you need <<merge_field>>.

This is the ONLY way to work around the lookbehind deficit in JS.
This works by completely consuming the bad part, and moves the current position past it
There is NO other way, don't be fooled.

This is done within a string replace callback.
Within the callback you can do the logic to control what get's written back as part of the replacement.

In our callback, if group 1 is matched, we just return group 1 thus not changing it's content.

If group 2 is matched, you can decide whether to just return group 2 changing nothing
(if you're just recording its position or pushing an array element),
or just change it to what you want.

var target = "href=\"<<merge_field>> and <<merge_field>> and href=\"<<merge_field>>";

var targ_new = 
    target.replace( /(href=["']<<merge_field>>)|(<<merge_field>>)/g,
       function( match, grp1, grp2 ) {
          if ( grp1 )
             return grp1;
          return "MRG"; // or return grp2 if just recording location
       }
    );

console.log( "Before:\r\n" + target);
console.log( "After:\r\n" + targ_new );