2010-10-03 6 views
38

Para regex, ¿cuál es la sintaxis para buscar hasta pero no incluir? Un poco como:Regex Until pero no incluida

Haystack: 
The quick red fox jumped over the lazy brown dog 

Expression: 
.*?quick -> and then everything until it hits the letter "z" but do not include z 

Respuesta

104

La forma explícita de decir "búsqueda hasta X pero sin incluir X" es:

(?:(?!X).)* 

donde X puede ser cualquier expresión regular.

En su caso, sin embargo, esto podría ser una exageración - aquí la forma más fácil sería

[^z]* 

Esto coincidirá con nada excepto z y por lo tanto dejar de hacerlo antes de la próxima z.

Entonces .*?quick[^z]* coincidirá con The quick fox jumps over the la.

Sin embargo, tan pronto como usted tiene más de una simple carta a tener en cuenta, (?:(?!X).)* entra en juego, por ejemplo

(?:(?!lazy).)* - por nada hasta el comienzo de la palabra lazy.

Esto está utilizando un lookahead assertion, más específicamente un aspecto negativo.

.*?quick(?:(?!lazy).)* coincidirá con The quick fox jumps over the.

Explicación:

(?:  # Match the following but do not capture it: 
(?!lazy) # (first assert that it's not possible to match "lazy" here 
.   # then match any character 
)*   # end of group, zero or more repetitions. 

Por otra parte, en la búsqueda de palabras clave, es posible que desee rodearlos de palabra anclas de contorno: \bfox\b sólo igualará la palabra completa fox pero no el zorro en foxy.

Nota

Si el texto que se ajustará también puede incluir saltos de línea, que tendrá que establecer el "punto detecta todos" opción de su motor de expresiones regulares. Por lo general, puede lograrlo anteponiendo (?s) a la expresión regular, pero eso no funciona en todos los motores de expresiones regulares (especialmente JavaScript).

solución alternativa:

En muchos casos, también se puede utilizar una solución más simple, más fácil de leer que utiliza un cuantificador perezoso. Mediante la adición de un ? a la * cuantificador, se trata de hacer coincidir el menor número de caracteres posible desde la posición actual:

.*?(?=(?:X)|$) 

coincidirá con cualquier número de caracteres, deteniéndose justo antes de X (que puede ser cualquier expresión regular) o el final de la cadena (si X no coincide). Es posible que también deba configurar la opción "dot matches all" para que esto funcione.(Nota: He añadido un grupo sin fines de captura de alrededor de X el fin de aislar de forma fiable desde la alternancia)

+0

+1 realmente agradable respuesta, desafortunadamente no funciona con 'grep', pero esta [respuesta] (http://stackoverflow.com/a/5979402/ 354831) hace. –

+0

@AlexandreLavoie: Interesante. ¿Por qué debería funcionar el otro y no este? Ambos usan aserciones de búsqueda anticipada. Quizás sea solo por el grupo '(?: ...)' no captor? ¿Funciona con '((?! X).) *'? –

+1

Realmente no lo sé, no soy un experto en expresiones regulares ni grep. Estaba usando 'grep' para filtrar las solicitudes de una sola base de datos desde mysql bin transformet en sql. Aquí está la bestia: 'grep -Po" (? S) use database_to_keep (. *?) (? =^Use) "mysql-bin.000045.sql> filtered.sql' –

0

probar este

(.*?quick.*?)z 
+0

Esto incluye la "z" en el partido, que es precisamente lo que el asker quiere evitar. Quizás la expresión regular está destinada a ser un término en '|' alternativa, y esa alternativa regex se usa para realizar múltiples coincidencias. Si la "z" es el comienzo de una cadena que coincidiría con ** otro ** término en la alternativa, esta coincidencia se perderá porque la "actual" ya está siendo consumida por la coincidencia actual. –

5

Un lookahead regex syntax puede ayudarle a alcanzar su objetivo. Por lo tanto una expresión regular para su ejemplo es

.*?quick.*?(?=z) 

Y es importante notar la coincidencia .*? vago antes de la (?=z) búsqueda hacia delante: la expresión coincide con una subcadena hasta que un primera ocurrencia de la letra z.

Aquí es C# código de muestra:

const string text = "The quick red fox jumped over the lazy brown dogz"; 

string lazy = new Regex(".*?quick.*?(?=z)").Match(text).Value; 
Console.WriteLine(lazy); // The quick red fox jumped over the la 

string greedy = new Regex(".*?quick.*(?=z)").Match(text).Value; 
Console.WriteLine(greedy); // The quick red fox jumped over the lazy brown dog 
Cuestiones relacionadas