Um regex para corresponder a uma substring que não é seguida por outra substring

Eu preciso de um regex que irá corresponder blahfooblah mas não blahfoobarblah

Eu quero que combine apenas foo e tudo ao redor foo, contanto que não seja seguido por bar.

Eu tentei usar isso: foo.*(?<!bar) que é bastante próximo, mas corresponde a blahfoobarblah . O olhar negativo por trás precisa corresponder a qualquer coisa e não apenas bar.

A linguagem específica que estou usando é o Clojure, que usa regexes de Java sob o capô.

EDIT: Mais especificamente, eu também preciso passar blahfooblahfoobarblah mas não blahfoobarblahblah .

Experimentar:

 /(?!.*bar)(?=.*foo)^(\w+)$/ 

Testes:

 blahfooblah # pass blahfooblahbarfail # fail somethingfoo # pass shouldbarfooshouldfail # fail barfoofail # fail 

Explicação da expressão regular

 NODE EXPLANATION -------------------------------------------------------------------------------- (?! look ahead to see if there is not: -------------------------------------------------------------------------------- .* any character except \n (0 or more times (matching the most amount possible)) -------------------------------------------------------------------------------- bar 'bar' -------------------------------------------------------------------------------- ) end of look-ahead -------------------------------------------------------------------------------- (?= look ahead to see if there is: -------------------------------------------------------------------------------- .* any character except \n (0 or more times (matching the most amount possible)) -------------------------------------------------------------------------------- foo 'foo' -------------------------------------------------------------------------------- ) end of look-ahead -------------------------------------------------------------------------------- ^ the beginning of the string -------------------------------------------------------------------------------- ( group and capture to \1: -------------------------------------------------------------------------------- \w+ word characters (az, AZ, 0-9, _) (1 or more times (matching the most amount possible)) -------------------------------------------------------------------------------- ) end of \1 -------------------------------------------------------------------------------- $ before an optional \n, and the end of the string 

Outro regex

Se você quer apenas excluir a bar quando está diretamente após o foo , você pode usar

 /(?!.*foobar)(?=.*foo)^(\w+)$/ 

Editar

Você atualizou sua pergunta para torná-la específica.

 /(?=.*foo(?!bar))^(\w+)$/ 

Novos testes

 fooshouldbarpass # pass butnotfoobarfail # fail fooshouldpassevenwithfoobar # pass nofuuhere # fail 

Nova explicação

(?=.*foo(?!bar)) garante que um foo seja encontrado, mas não é seguido diretamente da bar

Para coincidir com um foo seguinte por algo que não começa com bar , tente

 foo(?!bar) 

Sua versão com lookbehind negativo é efetivamente “combinar com um foo seguido por algo que não termina na bar “. barblah .* barblah todo o barblah , e o (? um retrospecto do lah e verifica se ele não corresponde à bar , o que não acontece, então o padrão inteiro corresponde.

Use um olhar negativo à frente:

 \s*(?!\w*(bar)\w*)\w*(foo)\w*\s* 

Isso funcionou para mim, espero que ajude. Boa sorte!

Sua solicitação de correspondência específica pode ser correspondida por:

 \w+foo(?!bar)\w+ 

Isso vai combinar blahfooblahfoobarblah mas não blahfoobarblahblah .

O problema com o seu regex de foo.*(? é o .* Após foo . Ele corresponde a muitos dos caracteres, incluindo caracteres após a bar .

Você escreveu um comentário sugerindo que você goste disso para trabalhar combinando todas as palavras em uma string, em vez da string inteira em si.

Em vez de misturar tudo isso em um comentário, estou postando como uma nova resposta.

Novo Regex

 /(?=\w*foo(?!bar))(\w+)/ 

Texto de amostra

foowithbar fooevenwithfoobar notfoobar foohere notfoobarhere butfooisokherebar notfoobarhere andnofuu needsfoo

Fósforos

foowithbar fooevenwithfoobar foohere butfooisokherebar needsfoo