2010-05-25 19 views
6

Necesito buscar líneas en un archivo CSV que termine en una cadena no terminada y comilla doble.Regex para encontrar una cadena sin terminar

Por ejemplo:

1,2,a,b,"dog","rabbit 

coincidiría mientras que

1,2,a,b,"dog","rabbit","cat bird" 
1,2,a,b,"dog",rabbit 

no lo haría.

tengo muy limitada experiencia con las expresiones regulares, y lo único que podía pensar es algo así como

"[^"]*$ 

Sin embargo, que coincide con la última cita al final de la línea.

¿Cómo se haría esto?

+1

¿Qué hay de ' "a \" BC "'o'" a "" bc" '? – SLaks

+0

supongamos que hay no comillas "intermedios"(sin comillas anidadas) –

Respuesta

5

Suponiendo que no se puedan escapar las cotizaciones, debe probar la paridad de las cotizaciones (asegurándose de que haya un número par de ellas en lugar de impares). Las expresiones regulares son geniales para eso:

^(([^"]*"){2})*[^"]*$ 

Eso coincidirá con todas las líneas con un número par de citas. Puede invertir el resultado para todas las cadenas con un número impar. O simplemente puede añadir otro ([^"]*") parte por el principio:

^[^"]*"(([^"]*"){2})*[^"]*$ 

Del mismo modo, si usted tiene acceso a los operadores renuentes en lugar de los codiciosos se puede utilizar una expresión más simple buscando:

^((.*"){2})*.*$   #even 
^.*"((.*"){2})*.*$  #odd 

Ahora, si se pueden escapar las citas, se trata de una pregunta completamente diferente, pero el enfoque sería similar: determinar la paridad de las comillas no guardadas.

+0

¿No debería haber algunos signos de interrogación en esas dos últimas expresiones regulares? Pero lo recomendaría contra ese enfoque, incluso * con * cuantificadores reacios, por la razón @SLaks mencionó: potencial retroceso fugitivo. Su primer enfoque debe ser seguro porque ninguna parte de la expresión regular puede coincidir con los mismos caracteres que una parte vecina - todo coincide con una cita o no-quote. –

+0

@Alan: Con respecto a los signos de interrogación, depende de su dialecto de expresiones regulares. Algunos dialectos de expresiones regulares usan '*?' como el reacio Kleene clo seguro, mientras que otros requieren que asigne banderas a la expresión regular para decirle al intérprete que los cierres de Kleene son reacios. Otros pueden considerarlos reacios por defecto y necesitan que se les diga explícitamente que son codiciosos. – Welbog

+0

No conozco ningún sabor regex que trate los cuantificadores como reacios por defecto. PHP tiene el modificador 'U', lo que los hace reacios a menos que use el signo de interrogación para hacerlos codiciosos. Mucha gente, yo entre ellos, creo que la característica fue un error, y que los usuarios deben desaconsejarse fuertemente de usarla. Cualquier beneficio que traiga es más que anulado por la confusión que causa. –

4

Suponiendo que las cadenas no pueden contener ", es necesario para que coincida con una cadena que tiene un número impar de cotizaciones, así:

([^"]*("[^"]*")?)*"

Tenga en cuenta que este es vulnerable a un ataque DDoS.

Esto coincidirá con cero o más conjuntos de ejecución sin cita, seguidos por las cadenas entre comillas.

+0

¿Por qué sería vulnerable a un ataque DDoS? –

+0

¡Es anidados expandos. http://msdn.microsoft.com/en-us/magazine/ff646973.aspx (La otra respuesta también es vulnerable) – SLaks

0

para evitar "expandos anidados":

egrep -v '^[^"]*("[^"]*"[^"]*)*[^"]*$' my_file 
+0

Eso sigue anidado expando (Un término mejor sería una repetición anidada). – SLaks

+0

Ah. Bien. Estaba leyendo esto como "cosas entre paréntesis anidadas". – DVK

1

prueba este:

".+[^"](,|$) 

Esto coincide con una cotización (en cualquier parte de la línea), seguido (avidez) por nada pero otra cita antes del final de la línea o una coma.

El efecto neto es que solo coincidirá con líneas con cadenas entre comillas colgantes.

Creo que incluso es inmune a los "ataques de expansiones anidadas" (vivimos en un mundo muy peligroso ...)

Cuestiones relacionadas