2011-11-23 27 views
22

Mi problema es que quiero comprobar la cadena de navegación con expresiones regulares puras.¿Hay una expresión regular para que coincida con una cadena que contiene A pero no contiene B

Mozilla/5.0 (Linux; U; Android 3.0; en-us; Xoom Build/HRI39) AppleWebKit/534.13 (KHTML, like Gecko) Version/4.0 Safari/534.13 

-> debe coincidir con

Mozilla/5.0 (Linux; U; Android 2.2.1; en-us; Nexus One Build/FRG83) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1 

no debe coincidir con

mi solución es tratado: /?((?<=Android)(?:[^])*?(?=Mobile))/i pero coincide exactamente equivocado.

+2

¿qué idioma, sabor regex? http://www.regular-expressions.info/tools.html – sehe

+0

No es tan fácil: [http://stackoverflow.com/q/8186424/241506][1] [1]: http://stackoverflow.com/q/8186424/241506 – VMykyt

+0

¿Qué quiere expresar con '(?: [^]) *?'? – stema

Respuesta

2

que acababa de romper hacia arriba

if ((m/Android/i) && (m/Safari/i) && !(m/Mobile Safari/i)) 

Dicho esto, dependiendo de flaviour expresiones regulares, que podría combinar

if ((m/Android/i) && (m/(?<!Mobile)Safari/i)) 

o incluso

if (m/Android.*(?<!Mobile)Safari/i) 

FYI ver Lookahead/lookbehind


actualización probado estas bien con sabor Perl5 expresiones regulares (posiblemente el sabor más popular):

perl -ne 'print "$. yes\n" if m/Android.*(?<!Mobile)Safari/i' 

Shows:

1 yes 

para la entrada dada en el PO

+0

Probado ahora con Perl5 compatible regexen – sehe

2

Con algunas implementaciones de expresiones regulares, puede usar una aseveración negativa de mirar hacia atrás. por la documentación, una búsqueda hacia atrás negativa por escrito como (?<!...) partidos sólo si la posición actual en la cadena no está precedido por un partido para ...

Aquí hay un script interactivo de Python muestra cómo utilizar de búsqueda hacia atrás negativa con sus cadenas de muestra:

>>> s = "Mozilla/5.0 (Linux; U; Android 3.0; en-us; Xoom Build/HRI39) AppleWebKit/534.13 (KHTML, like Gecko) Version/4.0 Safari/534.13" 
>>> bool(re.search(r'Android.*(?<! Mobile) Safari', s)) 
True 

>>> t = "Mozilla/5.0 (Linux; U; Android 2.2.1; en-us; Nexus One Build/FRG83) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1" 
>>> bool(re.search(r'Android.*(?<! Mobile) Safari', t)) 
False 
37

Utiliza las aserciones de anticipación para comprobar si una cadena contiene una palabra o no.

Si desea asegurarse de que la cadena contiene "Android" en algún lugar que puede hacerlo de esta manera:

^(?=.*Android).* 

También puede combinarlos, para asegurarse de que contiene "Android" en algún lugar Y "móvil" en algún lugar:

^(?=.*Android)(?=.*Mobile).* 

Si desea asegurarse de que una determinada palabra no está en la cadena, utilice el aspecto negativo delante:

^(?=.*Android)(?!.*Mobile).* 

Esto requeriría la palabra "Android para estar en la cadena y la palabra" Mobile "no está permitida en la cadena. La parte .* coincide con la cadena/fila completa cuando las aserciones al principio son verdaderas.

Ver here on Regexr

+0

+1 para el enfoque puro-regex más simple, pero lo escribiría como '^ (? =. * Android) (?!. * Móvil). *'. De lo contrario, los lookaheads se aplicarán en todas las posiciones o hasta que ambos tengan éxito. Tus expresiones regulares funcionan como se espera porque las cabezas de mirada positivas siempre fallan en todas partes, pero al principio, pero ¿y si solo tienes cabezas negativas? –

+0

@ AlanMoore gracias por la sugerencia, edité mi respuesta usándolo. – stema

Cuestiones relacionadas