2012-07-23 14 views
14

¿Cómo podré buscar palabras clave que no estén dentro de una cadena?palabras clave de concordancia regex que no están entre comillas

Por ejemplo, si tengo el texto:

Hola este texto es un ejemplo.

bla bla bla "este texto está dentro de una cadena"

"cadena aleatoria" más texto bla bla bla "foo"

me gustaría ser capaz de igualar todas las palabras text que no están dentro de " ". En otra me gustaría coincidir:

enter image description here

nota no quiero para que coincida con el texto que se resalta en rojo porque está dentro de una cadena


Posible solución:

He estado trabajando en ello y esto es lo que tengo hasta ahora:

(?s)((?<q>")|text)(?(q).*?"|)

nota que utiliza expresiones regulares como la sentencia if: (? (Predicado) verdadera alternativa | falsa alternativa)

así, el texto se lee:

hallazgo "o texto. Si encuentra "luego continuar seleccionando hasta encontrar" otra vez (. *? ") Si usted encuentra el texto a continuación, no hacer nada ...

cuando corro que la expresión regular que coincida con la cadena completa sin embargo. Lo pregunto pregunta con el propósito de aprender. Sé que puedo eliminar todas las cadenas y luego buscar lo que necesito.

+0

¿Ha intentado con un generador de expresiones regulares en línea como: http://txt2re.com/index-csharp.php3 – Surfbutler

+2

¿Por qué le gustaría hacer coincidir una cadena que sabe lo que es? ¿Qué planeas hacer con el resultado? La intención es importante para que otros puedan dar una respuesta adecuada. – Mithon

+0

No necesita saber el propósito de la pregunta para poder responderla. También supones que él sabe lo que es la cadena. Solo da ejemplos para demostrar lo que está tratando de hacer y esos no son necesariamente lo que usará finalmente. Está buscando un resultado específico y no nos corresponde cómo se usará ese resultado. –

Respuesta

20

Aquí es una respuesta:

(?<=^([^"]|"[^"]*")*)text 

Esto significa:

(?<=  # preceded by... 
^   # the start of the string, then 
([^"]  # either not a quote character 
|"[^"]*" # or a full string 
)*   # as many times as you want 
) 
text  # then the text 

Se puede extender fácilmente a este manejar cadenas que contengan escapes también.

En código C#:

Regex.Match("bla bla bla \"this text is inside a string\"", 
      "(?<=^([^\"]|\"[^\"]*\")*)text", RegexOptions.ExplicitCapture); 

Agregado de comentario de discusión - versión extendida (partido en función de cada línea y manejar escapes). Utilice RegexOptions.Multiline para esto:

(?<=^([^"\r\n]|"([^"\\\r\n]|\\.)*")*)text 

En una cadena de C# será similar a:

"(?<=^([^\"\r\n]|\"([^\"\\\\\r\n]|\\\\.)*\")*)text" 

Desde ahora quiere utilizar ** en lugar de " aquí es una versión para que:

(?<=^([^*\r\n]|\*(?!\*)|\*\*([^*\\\r\n]|\\.|\*(?!\*))*\*\*)*)text 

Explicación:

(?<=  # preceded by 
^   # start of line 
(  # either 
[^*\r\n]| # not a star or line break 
\*(?!\*)| # or a single star (star not followed by another star) 
    \*\*  # or 2 stars, followed by... 
    ([^*\\\r\n] # either: not a star or a backslash or a linebreak 
    |\\.  # or an escaped char 
    |\*(?!\*) # or a single star 
    )*   # as many times as you want 
    \*\*  # ended with 2 stars 
)*  # as many times as you want 
) 
text  # then the text 

Desde esta versión no contiene " caracteres Es más limpio de utilizar una cadena literal:

@"(?<=^([^*\r\n]|\*(?!\*)|\*\*([^*\\\r\n]|\\.|\*(?!\*))*\*\*)*)text" 
+0

Porges gracias por la ayuda! si tuviera dónde: '" \ r \ n text \ r \ n "bla bla ...' eso no hace una coincidencia ... Supongo que la razón es porque '[^"] 'continuará en la siguiente línea ... –

+1

@TonoNam: si desea que coincida por línea, cambie ambos '[^"] 'a' [^ "\ r \ n]' y agregue 'RegexOptions.Multiline' a las opciones. – porges

+0

gracias! Eso fue muy útil –

5

Esto puede ser bastante complicado, pero este es un método potencial que funciona asegurándose de que haya un número par de comillas entre el texto coincidente y el final de la cadena:

text(?=[^"]*(?:"[^"]*"[^"]*)*$) 

Reemplazar text con la expresión regular que desea hacer coincidir.

Rubular: http://www.rubular.com/r/cut5SeWxyK

Explicación:

text   # match the literal characters 'text' 
(?=    # start lookahead 
    [^"]*   # match any number of non-quote characters 
    (?:   # start non-capturing group, repeated zero or more times 
     "[^"]*"  # one quoted portion of text 
     [^"]*   # any number of non-quote characters 
    )*    # end non-capturing group 
    $    # match end of the string 
)    # end lookahead 
+0

que no coincide con el último texto. ¡Pero es muy útil saber! +1 gracias por la ayuda. –

1

yo simplemente con avidez coincidir con el texto de comillas dentro de un grupo sin fines de captura para filtrar hacia fuera y luego usar una la captura de grupo para la respuesta no cotizado, así:

".*(?:text).*"|(text) 

la que es posible que desee afinar un poco de palabras-límites, etc. Pero esto debe llegar a donde quieres ir, y ser una muestra claro y entendible.

Cuestiones relacionadas