Preciso projetar um regex que combine 4 partes separadas por um delimitador ( :
neste caso). As 4 partes devem estar em ordem, e o delimitador deve estar presente entre cada parte, mas as partes são todas opcionais.
Todos eles devem corresponder:
A
B
C
D
A:B
A:C
A:D
B:C
B:D
C:D
A:B:C
A:B:D
A:C:D
B:C:D
A:B:C:D
Enquanto isso, eles não devem corresponder.
A: // cannot end with delimiter
:C // cannot start with delimiter
ABC // cannot omit delimiter
A:BC // cannot omit delimiter
A::B // cannot duplicate delimiter
... // many other possible non-matches
Meu problema é que não sei como corresponder ao delimitador.
- Eu tentei
^(A)?:?(B)?$
, mas depois vai corresponderAB
. - Eu tentei
^(A:)?(B)?$
, mas depois vai corresponderA:
. - Posso enumerar manualmente todos os 15 tipos de correspondência, mas isso é uma grande bagunça (
^(A)|(B)|(C)|(D)|(A:B)|(A:C)...........$
). No regex real,A
eB
, etc. são mais complexos. - Tentei uma enumeração mais concisa como esta
^((A)|((A:)?((B)|((B:)?((C)|((C:)?(D)))))))$
, mas ainda parece uma bagunça total para mim. Vou com esta opção se não encontrar uma resposta melhor.
Você pode tornar os dois pontos opcionais , mas use limites de palavras para obrigá-los entre letras:
Veja esta demonstração em regex101
Ou você torna todos os caracteres opcionais e usa um lookahead no início para validar o formato:
Outra demonstração em regex101 (
\w
corresponde a um caractere de palavra)Se strings vazias devem ser correspondidas, basta anexar
|^$
a qualquer um dos dois padrões ( regex101 demo ) ou envolver qualquer um deles em outro grupo^(?:
opcional)?$
( demo ).Não há necessidade de fazer nada extravagante. Basta combinar uma letra e dois pontos de 0 a 3 vezes, seguidos por uma letra:
^(?:[A-D]:){0,3}[A-D]$
https://regex101.com/r/AsjmWQ/1
Se a ordem for importante, você pode invalidar correspondências fora de ordem usando lookaround no início do padrão, embora essa abordagem leve rapidamente a padrões complicados se seus dados reais contiverem mais de 4 valores possíveis:
^(?!.*B(?=.*A))(?!.*C(?=.*[AB]))(?!.*D(?=.*[ABC]))(?:[A-D]:){0,3}[A-D]$
https://regex101.com/r/kdz9xG/1