How can I achieve this regex without a look ahead assertion?

72 views Asked by At

I have regex which uses a look ahead assertion to match strings of the format {{ x }}. The regex is /(?<=\{\{\s)[^}\s]+(?=\s*\}\})/gm

How can I achieve this without using a look ahead assertion?

3

There are 3 answers

0
Alberto Fecchi On

Try with this:

\{\{\s([^}\s]+)\s*\}\}

Your result will be inside the first group (the rules inside ())

1
Heiko Theißen On

Adding to the other answers, if you want a list of all "x values", you can produce one by repeatedly evaluating m[1], which is the first group, where m is one of the matches.

The following variants with and without lookaround are equivalent:

/* With lookaround */
const s = "{{ 1 }}{{ 2 }}";
console.log(s.match(/(?<=\{\{\s*)[^}\s]+(?=\s*\}\})/gm));
/* Without lookaround */
for (var matches = [], m, regex = /\{\{\s*([^}\s]+)\s*\}\}/gm; m = regex.exec(s);)
  matches.push(m[1]);
console.log(matches);

The question remains, however: Why do you want to avoid lookarounds?

0
Peter Seliger On

A regex like /\{\{\s*([^}]+?)\s*\}\}/g which does match more loose variants of the OP's {{ x }}-pattern by making use of ...

  • capturing groups for targeting every character which is not a closing curly brace except of (optional) leading and trailing whitespace (sequences) ... and a ...

  • lazy (non greedy) quantifier for the pattern's termination of an optional whitespace (sequence) followed by two closing curly braces ... applied via ...

  • matchAll and an additional mapping task ...

... does the trick.

const sampleDate =
`{{1}} {{}} {{  24 56 48 }}
   {{   245648}}{{ 123  }}`;

console.log(
  // see ... [https://regex101.com/r/uPFdrO/1]

  [...sampleDate.matchAll(/\{\{\s*([^}]+?)\s*\}\}/g)]
    .map(([match, capture]) => capture)
);
.as-console-wrapper { min-height: 100%!important; top: 0; }

And altering the capturing pattern from [^}] to [^}\s] does enforce captures which do not contain any space characters. The lazy quantifier then can be dropped as well ...

const sampleDate =
`{{1}} {{}} {{  24 56 48 }}
   {{   245648}}{{ 123  }}`;

console.log(
  // see ... [https://regex101.com/r/uPFdrO/2]

  [...sampleDate.matchAll(/\{\{\s*([^}\s]+)\s*\}\}/g)]
    .map(([match, capture]) => capture)
);
.as-console-wrapper { min-height: 100%!important; top: 0; }