2012-08-08 19 views
15

que tienen un gran texto:expresiones regulares: Buscar cadena sin subcadena

"Big piece of text. This sentence includes 'regexp' word. And this 
sentence doesn't include that word" 

Necesito encontrar subcadena que comienza por 'este' y termina por 'palabra', pero no lo hace incluir la palabra 'regexp'.

En este caso, la cadena: "this sentence doesn't include that word" es exactamente lo que quiero recibir.

¿Cómo puedo hacer esto a través de las expresiones regulares?

+0

Sus reglas son confusas o ha cometido un error con su resultado esperado. Por qué no "Y" y por qué no "Gran trozo de texto". – sjakubowski

+0

@sjakubowski "la subcadena comienza por 'esto' y termina por 'palabra'" – Mathletics

+0

Estas reglas son confusas pero correctas. Pasé mucho tiempo buscando algo en google pero no encontré nada. – Artem

Respuesta

27

Con una opción ignorar caso, el siguiente debería funcionar:

\bthis\b(?:(?!\bregexp\b).)*?\bword\b 

Ejemplo: http://www.rubular.com/r/g6tYcOy8IT

Explicación:

\bthis\b   # match the word 'this', \b is for word boundaries 
(?:    # start group, repeated zero or more times, as few as possible 
    (?!\bregexp\b) # fail if 'regexp' can be matched (negative lookahead) 
    .     # match any single character 
)*?    # end group 
\bword\b   # match 'word' 

El \b que rodea a cada palabra se asegura de que no son coincidentes en subcadenas, al igual que coincida con el 'presente' en 'cardo', o la 'palabra' en 'prolijo'.

Esto funciona comprobando cada carácter entre su palabra de inicio y su palabra final para asegurarse de que la palabra excluida no ocurra.

+2

¡Es exactamente lo que necesito! ¡Gracias! – Artem

+2

+1 para la buena explicación de la expresión regular y el enlace para jugar con ella. Pude aplicar esto a algo similar y habría tenido problemas sin la explicación. Estoy harto de respuestas que solo dan un poco de código sin decir cómo funciona. –

+0

¡Me ayudaste mucho! ¡Gracias! –

3

Utilice asambleas de búsqueda anticipada.

Cuando desea comprobar si una cadena no contiene otra subcadena, se puede escribir:

/^(?!.*substring)/ 

Debe marcar también el comienzo y el final de la línea de this y word:

/^this(?!.*substring).*word$/ 

Otro problema aquí es que no trabaja buscando cadenas, quiere encontrar oraciones (si entiendo su tarea correcta).

Así que la solución es similar a esto:

perl -e ' 
    local $/; 
    $_=<>; 
    while($_ =~ /(.*?[.])/g) { 
    $s=$1; 
    print $s if $s =~ /^this(?!.*substring).*word[.]$/ 
    };' 

Ejemplo de uso:

$ cat 1.pl 
local $/; 
$_=<>; 
while($_ =~ /(.*?[.])/g) { 
    $s=$1; 
    print $s if $s =~ /^\s*this(?!.*regexp).*word[.]/i; 
}; 

$ cat 1.txt 
This sentence has the "regexp" word. This sentence doesn't have the word. This sentence does have the "regexp" word again. 

$ cat 1.txt | perl 1.pl 
This sentence doesn't have the word. 
+0

Esa búsqueda anticipada sola no hará el trabajo; necesita usar lookaheads anidados. Y el fragmento de código que sigue es bastante difícil de leer (no sé Perl) sin explicación. :/ – KRyan

+0

@DragoonWraith: ¿de qué estás hablando? Esta alma no resuelve la tarea. Puedes probarlo tú mismo. –

+0

Probé el RegEx publicado y no lo hizo. '(?!' impedirá que coincida con cualquier caso en el que aparezca la subcadena después de 'this' (del ejemplo), incluso si la subcadena aparece después de' word'. Usando un '(? :(?!' por FJ anidado ' La respuesta de s soluciona esto.No tengo Perl disponible para probar ese fragmento, pero no estoy aprendiendo nada al mirarlo, y por lo que puedo * decir que no es una solución RegEx de todos modos, ya que parece estar caminando manualmente a través de la cadena con ese bucle 'while'. La pregunta está etiquetada 'regex' no' perl'. – KRyan

Cuestiones relacionadas