Dadas duas strings (denotadas por A e B ) e um conjunto N de strings, preciso escrever uma expressão regular para testar se uma determinada string de entrada W contém uma substring S , onde S é qualquer substring que satisfaça todas as três condições a seguir: 1. começa com A ; 2. termina com B ; 3. qualquer elemento de N não ocorre na parte entre A e B (esta parte não se sobrepõe a A e B ).
Por exemplo, eu escolhi "ab"
como A , "bc"
como B , ["a", "cb", "cd"]
como N . Se "ec"
for a parte interna, então "abecbc"
é a string que satisfaz todas as três condições: se W contiver tal substring, a regex deve retornar true
. Minha primeira variante é a seguinte regex:
var T = /(?=ab.*bc)(?=(?!ab.*a.*bc))(?=(?!ab.*cb.*bc))(?=(?!ab.*cd.*bc))/;
Eu escolhi W = S = "abecbc"
. Esta regex funciona como esperado:
T.test("abecbc");
// true
Mas estou interessado no seguinte problema: como escrever uma regex funcionalmente equivalente sem usar o lookahead positivo (?=)
como o operador AND ?
Então minha segunda variante é a seguinte:
var R = /ab(?!.*?(?:a|cb|cd).*)bc/;
Mas R.test("abecbc")
avalia para false
. Então vamos dividir R
em três partes:
/ab(.*)/.test("abecbc")
retorna true
. Então
/(.*)bc/.test("abecbc")
retorna true
.
A parte interna (ou seja, a parte entre "ab"
e "bc"
) é "ec"
. E
/(?!.*?(?:a|cb|cd).*)/.test("ec")
retorna true
, o que é esperado. Então deve haver três verdades, e não há mais partes em R
. Então por que
/ab(?!.*?(?:a|cb|cd).*)bc/.test("abecbc")
avaliar para false
? E como escrever uma regex correta que resolva o problema descrito no primeiro parágrafo do post sem usar o lookahead positivo (?=)
como o operador AND ?
EDITAR
Minha pergunta não é uma duplicata desta pergunta : preciso de uma explicação de por que o regex específico ( R
) retorna false
em vez de true
. Outra diferença é que não preciso testar se a parte interna contém uma string especificada.
Sua tentativa de regex de
R = /ab(?!.*?(?:a|cb|cd).*)bc/
falha em corresponderabecbc
porque um padrão lookahead negativo é uma asserção de largura zero, então com sua regexbc
tem que seguir imediatamenteab
. E se você tentar consertá-lo adicionando.*
beforebc
então não há garantia de que uma correspondência dea|cb|cd
ocorra entreab
ebc
.Em vez disso, você pode capturar B e o que vem depois dele para poder usar a captura como um final em uma afirmação de lookahead negativa para evitar uma correspondência quando houver qualquer um de N entre A e B :
Demonstração: https://regex101.com/r/NqLbfV/4