-1

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?

Peter Seliger
  • 11,747
  • 3
  • 28
  • 37
williamsandonz
  • 15,864
  • 23
  • 100
  • 186
  • 1
    Why not simply use `\{\{\s*([^}\s]+)\s*\}\}` (capturing the part you want instead of using lookarounds to exclude the parts you don't want)? (I've also replaced `\s` with `\s*` for consistency of the opening `{{` with the closing `}}`). – Luatic Aug 11 '23 at 10:34

4 Answers4

2

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; }
Peter Seliger
  • 11,747
  • 3
  • 28
  • 37
1

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?

Heiko Theißen
  • 12,807
  • 2
  • 7
  • 31
0

Try with this:

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

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

desertnaut
  • 57,590
  • 26
  • 140
  • 166
Alberto Fecchi
  • 1,705
  • 12
  • 27
0
const regex = /{{\s([^}\s]+)\s}}/gm;
const input = "text {{ x }} and {{ y }}.";
const matches = input.match(regex);

if (matches) {
    const capturedContent = matches.map(match => match.replace(regex, '$1'));
    console.log(capturedContent);
}
Ubaid Ali
  • 19
  • 3