2009-12-28 29 views
19

Ok, entonces esto es algo completamente estúpido, pero esto es algo que simplemente nunca aprendí a hacer y es una molestia.Regex para todas las cadenas que no contengan una cadena?

Cómo especifico una cadena que no contiene una secuencia de otros caracteres. Por ejemplo, yo quiero buscar todas las líneas que no terminan en '.config'

Me gustaría pensar que simplemente lo que podía hacer

.*[^(\.config)]$ 

pero esto no funciona (¿por qué no?)

sé que puedo hacer

.*[^\.][^c][^o][^n][^f][^i][^g]$ 

pero por favor, por favor, por favor, dime que hay una manera mejor

+1

lo motor de expresiones regulares está usando? Pueden muy en las características compatibles. Debe etiquetar su pregunta con el motor que está utilizando. – Andrew

+1

¿por qué no usar 'grep -v" \ .config "'? – Lazer

+6

@Lazer - porque no todo en el mundo es un sistema * nix? –

Respuesta

40

Puede utilizar negative lookbehind, por ejemplo:

.*(?<!\.config)$ 

Esto coincide con todas las cadenas excepto aquellos que terminan con ".config"

+0

Esto funciona pero. * (?! = \. Config) $ no - Pensé que las dos sintaxis eran equivalentes. ¿Cualquier pista? –

+2

NO son equivalentes. (? Manu

+1

No, no lo son. La búsqueda anticipada negativa es '(?! Matchthis)', y su ejemplo no puede funcionar porque está mirando hacia adelante en un momento en que ya se encuentra al final de la cadena ('$'). –

2

A menos que esté "grepping" ... ya que no está utilizando el resultado de una coincidencia, ¿por qué no buscar las cadenas que terminan en .config y omitirlas? En Python:

import re 
isConfig = re.compile('\.config$') 
# List lst is given 
filteredList = [f.strip() for f in lst if not isConfig.match(f.strip())] 

Sospecho que esto funcionará más rápido que un re más complejo.

+1

A menos que esté desgranando, ¿por qué usar la expresión regular? Python tiene 'in' por una razón. Otros idiomas, estoy seguro, tienen soluciones similares. –

+0

Sí, esto es lo que hago ahora, pero lo mejor es saber cómo hacerlo en ambos sentidos. Me encontré con situaciones en las que esto ha forzado una sintaxis incómoda. –

2

Al usar el constructo [^], ha creado una clase de caracteres negados, que coincide con todos los caracteres excepto los que ha nombrado. Orden de los caracteres en el partido candidato no importa, por lo que este se producirá un error en cualquier cadena que tiene cualquiera de [(\.config) (o [)gi.\onc(])

Uso búsqueda negativa hacia delante, (con regexs Perl), así: (?!\.config$). Esto coincidirá con todas las cadenas que no coincidan con el literal ".config"

15

Su pregunta contiene dos preguntas, por lo que aquí hay algunas respuestas.

líneas de partido que no lo hacen contienen una determinada cadena (por ejemplo .config) en absoluto:

^(?:(?!\.config).)*$\r?\n? 

líneas de partido que no lo hacen final en una determinada cadena:

^.*(?<!\.config)$\r?\n? 

y, como bonificación: Coincidir con líneas que no comienzan con una determinada cadena:

^(?!\.config).*$\r?\n? 

(cada vez incluidos los caracteres de línea nueva, si están presentes).

Ah, y para responder por qué su versión no funciona: [^abc] significa "cualquier (1) carácter excepto a, b, o c".Su otra solución también fallaría en test.hg (ya que también termina en la letra g - su expresión regular mira a cada personaje en su lugar individual de toda la cadena de .config Es por eso que necesita lookaround para manejar este

2

Como usted ha pedido.. una "mejor manera":. me gustaría probar un enfoque de "filtrado" creo que es bastante fácil de leer y entender:

#!/usr/bin/perl 

while(<>) { 
    next if /\.config$/; # ignore the line if it ends with ".config" 
    print; 
} 

como se puede ver que he utilizado el código perl como un ejemplo, pero creo. ¿entiendes?

sumado: este enfoque también podría ser utilizado para más patrones filtro de cadena y todavía sigue siendo buena legible y fácil de entender,

next if /\.config$/; # ignore the line if it ends with ".config" 
    next if /\.ini$/; # ignore the line if it ends with ".ini" 
    next if /\.reg$/; # ignore the line if it ends with ".reg" 

    # now we have filtered out all the lines we want to skip 
    ... process only the lines we want to use ... 
0

que utilizan Regexpal antes de encontrar esta página y se le ocurrió la siguiente solución cuando quería para comprobar que una cadena no contiene una extensión de archivo:

^(.(?!\.[a-zA-Z0-9]{3,}))*$ Utilicé la opción de casilla m para poder presentar muchas líneas y ver cuáles de ellas coincidían o no.

por lo que encontrar una cadena que no contiene otra "^(.(?!" + expresión no desea + "))*$"

My article on the uses of this particular regex

Cuestiones relacionadas