Regex - Return only non repeated items

Viewed 40

I need to return only non-repeating elements from a string.

This is my current regex:

/{{([1-9]|[1-9][0-9])}}/gm

Here are some samples of what I need:

{{1}}{{2}}{{3}}{{4}}{{5}}{{1}} => {{1}}{{2}}{{3}}{{4}}{{5}}
{{1}}{{2}}{{3}}{{4}}{{2}}{{1}} => {{1}}{{2}}{{3}}{{4}}
{{1}}{{2}}{{2}}{{4}}{{1}}{{1}} => {{1}}{{2}}{{4}}

I have tried the following lookaround:

/{{([1-9]|[1-9][0-9])}}(?!.*\1)/gm

Kind of works for this example, but it get the last element instead of the first:

{{1}}{{2}}{{3}}{{4}}{{5}}{{1}} => {{2}}{{3}}{{4}}{{5}}{{1}}

With this example it don't work:

Olá, {{1}}

Só pra lembrar, sua consulta foi agendada para o dia {{2}} às {{3}}h.

Por favor, não se atrase

Se por acaso tiver algum imprevisto e não puder comparecer, nos avisem com {{4}}h de antecedência.

{{1}}, te esperamos aqui!

The string above returns all elements:

{{1}}{{2}}{{3}}{{4}}{{1}}
1 Answers

If I understand problem correctly, here is what you need:

  1. You want to match {{<num>}} patterns
  2. But don't want to match duplicates occurrence of same pattern
  3. Duplicates of {{<num>}} can occur any where in multiline text
  4. You prefer to match first occurrence of duplicates

Since you showed Javascript syntax of your regex, I am also using lookbehind feature in my regex as per modern Javascript behavior:

({{(?:[1-9]|[1-9]\d)}})(?<!^(?:[^]*\1){2})

RegEx Breakup:

  • ({{(?:[1-9]|[1-9]\d)}}): Match {{<num>}} text and capture in group #1
  • (?<!^(?:[^]*\1){2}): Negative lookbehind with a dynamic length to assert failure if we have 2 repeats of capture group #1
Related