Search code examples
regex

How to exclude a prior match from a future match


I'm trying to write a regex, where the same group of terms is looked for twice, but I want to avoid matching the same term twice. If a term is found in the first group, it should not be matched in the second group.

/(a|b).*?(a|b)/

This would match:

a a
a b
b a
b b

But I do not want to match a a and b b, only a b and b a. The method should work with any number of terms, (a|b) is just an example but it could be something like:

/(anna|beat|chris|dirk).*?(anna|beat|chris|dirk)/

Solution

  • Try:

    ^(?<options>a|b) (?!\1)(?P>options)$
    

    See: regex101


    Explanation

    • ^...$: force the match to span the whole line
    • (?<options>...): define capturegroup "options" to match
      • a|b: a or b, and match.
    • : match literal space
    • (?!\1): ensure next character is not what has been matched to the first group
    • (?P>options): then find an other value from "options" by using it as a subroutine

    This extends to:

    ^(?<options>a|b|c) (?!\1)((?P>options)) (?!\1|\2)(?P>options)$
    

    See: regex101