Expresión regular para una cadena que contiene una palabra pero no otra

103

Estoy configurando algunos objetivos en Google Analytics y me vendría bien un poco de ayuda con las expresiones regulares.

Digamos que tengo 4 URL

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

Quiero crear una expresión que identifique cualquier URL que contenga el selector de cadena = tamaño pero NO contenga detalles.cfm

Sé que para encontrar una cadena que NO contenga otra cadena, puedo usar esta expresión:

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

Pero, no estoy seguro de cómo agregar la porción selector = tamaño .

¡Cualquier ayuda será muy apreciada!

Chris Stahl
fuente

Respuestas:

144

Esto debería hacerlo:

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

^.*selector=size.*$debe ser lo suficientemente claro. El primer bit (?!.*details.cfm)es un avance negativo: antes de hacer coincidir la cadena, comprueba que la cadena no contiene "detalles.cfm" (con cualquier número de caracteres antes).

Kobi
fuente
8
Para su información, visite regexr.com para ver una buena manera de probar estas expresiones.
Joshua Pinter
Olvídese siempre de la anticipación negativa y es muy útil
Alexei Blue
"http://www.anydotcom.com/test/search.cfm?metric=blah&selector=sized&value=1" =~ /^(?!.*details\.cfm).*selector=size.*$/ #=> 0Es incorrecto. (Tenga en cuenta que la cadena contiene "...selector=sized..."). Además, ¿ .*$por qué al final?
Cary Swoveland
4

regex podría ser (sintaxis de perl):

`/^[(^(?!.*details\.cfm).*selector=size.*)|(selector=size.*^(?!.*details\.cfm).*)]$/`
djipko
fuente
Esta es una expresión regular corrupta, los corchetes convierten todas las secuencias de patrones en una combinación de caracteres individuales.
Wiktor Stribiżew
2
^(?=.*selector=size)(?:(?!details\.cfm).)+$

Si su motor de expresiones regulares admitía cuantificadores posesivos (aunque sospecho que Google Analytics no lo hace), supongo que esto funcionará mejor para grandes conjuntos de entrada:

^[^?]*+(?<!details\.cfm).*?selector=size.*$
Tomalak
fuente
Esto supone selector=sizeque siempre es antes details.cfm, que no es el caso en la última URL.
Kobi
Solo para aclarar esto, no fui yo. No veo por qué alguien rechazaría dos respuestas aquí, ambas son correctas.
Kobi
@Kobi: Esto debería haber sido una anticipación, corregido. Ah, y por cierto, no sospeché que fuera su voto en contra.
Tomalak
0

Estaba buscando una manera de evitar la --line-bufferedcola en una situación similar, ya que el OP y la solución de Kobi funcionan muy bien para mí. En mi caso, excluir líneas con "bot" o "araña" mientras se incluyen ' / '(para mi documento raíz).

Mi comando original:

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

Ahora se convierte (con -Pperl switch):

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