Expressão regular para uma string contendo uma palavra, mas não outra

103

Estou definindo alguns objetivos no Google Analytics e poderia usar um pouco de ajuda regex.

Digamos que tenho 4 URLs

http://www.anydotcom.com/test/search.cfm?metric=blah&selector=size&value=1
http://www.anydotcom.com/test/search.cfm?metric=blah2&selector=style&value=1
http://www.anydotcom.com/test/search.cfm?metric=blah3&selector=size&value=1
http://www.anydotcom.com/test/details.cfm?metric=blah&selector=size&value=1

Quero criar uma expressão que identificará qualquer URL que contenha a string selector = size, mas NÃO contenha details.cfm

Eu sei que para encontrar uma string que NÃO contenha outra string posso usar esta expressão:

(^((?!details.cfm).)*$)

Mas, não tenho certeza de como adicionar a parte selector = size .

Qualquer ajuda seria muito apreciada!

Chris Stahl
fonte

Respostas:

144

Isso deve servir:

^(?!.*details\.cfm).*selector=size.*$

^.*selector=size.*$deve ser claro o suficiente. O primeiro bit (?!.*details.cfm)é um look-ahead negativo: antes de combinar a string, ele verifica se a string não contém "details.cfm" (com qualquer número de caracteres antes dele).

Kobi
fonte
8
Para sua informação, confira regexr.com para uma boa maneira de testar essas expressões.
Joshua Pinter
Sempre se esqueça do lookahead negativo e é tão útil
Alexei Blue
"http://www.anydotcom.com/test/search.cfm?metric=blah&selector=sized&value=1" =~ /^(?!.*details\.cfm).*selector=size.*$/ #=> 0está incorreto. (Observe que a string contém "...selector=sized...".) Além disso, por que .*$no final?
Cary Swoveland
4

regex pode ser (sintaxe perl):

`/^[(^(?!.*details\.cfm).*selector=size.*)|(selector=size.*^(?!.*details\.cfm).*)]$/`
Djipko
fonte
Este é um regex corrompido, os colchetes transformam todas as sequências de padrões em combinações de caracteres individuais.
Wiktor Stribiżew
2
^(?=.*selector=size)(?:(?!details\.cfm).)+$

Se o seu mecanismo regex suportava quantificadores posessivos (embora eu suspeite que o Google Analytics não suporta), então acho que isso terá um desempenho melhor para grandes conjuntos de entrada:

^[^?]*+(?<!details\.cfm).*?selector=size.*$
Tomalak
fonte
Isso pressupõe que selector=sizeé sempre anterior details.cfm, o que não é o caso no último url.
Kobi
Só para esclarecer isso, não fui eu. Não consigo ver por que alguém votaria contra duas respostas aqui, ambas estão corretas.
Kobi
@Kobi: Isso deveria ter sido uma antecipação, corrigido. Ah, a propósito, não suspeitei que fosse o seu voto negativo.
Tomalak
0

Eu estava procurando uma maneira de evitar --line-buffereduma situação semelhante quando o OP e a solução de Kobi funcionam muito bem para mim. No meu caso, excluindo linhas com "bot" ou "spider" enquanto inclui ' / '(para o meu documento raiz).

Meu comando original:

tail -f mylogfile | grep --line-buffered -v 'bot\|spider' | grep ' / '

Agora se torna (com o -Pswitch perl):

tail -f mylogfile | grep -P '^(?!.*(bot|spider)).*\s\/\s.*$'
roon
fonte