2010-12-18 20 views
7

Hola expertos expresión regular,expresiones regulares - Cómo reemplazar un carácter entre comillas

nunca ha habido un problema de manipulación de cadenas que no podía resolver con expresiones regulares hasta ahora, al menos de una manera elegante con una sola paso. Aquí está la muestra de datos que estoy trabajando con:.

0 "sección 1", "(7) Entrega de 'certificado' fuera de la Estados Unidos prohíbe Dado que tanto la sección 339 de la ley 1940, 68/y la sección 341 de la presente ley son explícito en su afirmación de que el certificado se aportará el ciudadano , sólo si dicho individuo está en el tiempo dentro de los Estados Unidos, que está claro que el documento no ha podido y no se puede entregar fuera del Estados Unidos. ", Http: //www.google.co m/

1, "section2" ,, http: //www.google.com/

2, "sección3", ",,", http: //www.google.com/

Esta es una sección de un archivo CSV mucho más grande. Con una expresión regular elegante, me gustaría reemplazar solo todas las comas que aparecen dentro de las comillas dobles con un carácter de guión bajo (_). Es importante que la expresión regular NO reemplace las comas fuera de las comillas, ya que eso podría arruinar la estructura de datos CSV.

Gracias, Tom

-

ACLARACIÓN:

Lo siento chicos, he publicado la cuestión sin aclarar completamente mi situación, así que vamos a resumir a continuación:

  • Asumir que las comillas entre comillas ya se han escapado (las comillas entre comillas en un archivo CSV guardado por Excel están representadas por "" o """ etc., por lo que se reemplazan fácilmente de antemano).
  • Estoy trabajando dentro de JavaScript.

Utilizando el texto de ejemplo anterior, esto es lo que debe ser similar después de ejecutar la sustitución de expresiones regulares (no debe haber un total de 5 reemplazos):

0 "sección 1", "(7) Entrega de 'certificado' fuera de la Estados Unidos prohibida. Dado que tanto la sección 339 del 1940 statute_ 68/y la sección 341 de la presente ley son explícito en su afirmación de que el certificado debe haber en los citizen_ solo si tal indi vidual está en el tiempo dentro de los Estados States_ que está claro que el documento podría no y no puede ser enviado fuera de la Estados Unidos "http: //www.google.com/

1". sección2 ",, http: //www.google.com/

2, "sección3", "__", http: //www.google.com/

+1

¿Cómo estás escapando citas entre comillas? –

+0

@ Assaf, buena pregunta; por favor mira mi aclaración arriba. – 10basetom

Respuesta

12

Yo te ayudaré, pero usted tiene que prometer dejar de usar la palabra "elegante". Ha estado trabajando demasiado duro últimamente, y merece un descanso. : P

(?m),(?=[^"]*"(?:[^"\r\n]*"[^"]*")*[^"\r\n]*$) 

Esto coincide con una coma si, entre la coma y el final del registro, hay un número impar de comillas. Asumo un formato CSV estándar, en el cual un registro termina en el siguiente separador de línea que no está entre comillas. Los separadores de línea son legales dentro de los campos entrecomillados, al igual que las comillas si se han escapado con otra cita.

Dependiendo del sabor de la expresión regular que está utilizando, puede que tenga que usar \r?$ en lugar de solo $. En .NET, por ejemplo, solo el salto de línea (\n) se considera un separador de línea. Pero en Java, $ coincide con el \r en \r\n, pero no entre \r y \n (a menos que establezca el modo UNIX_LINES).

+0

Alan Moore, eres un experto en expresiones regulares :-). De todas las soluciones que he recibido aquí (y en otros lugares), su única expresión súper regular fue capaz de hacer exactamente lo que describí en mi pregunta, incluso antes de publicar mi aclaración. Puntos de bonificación, y SÍ, su solución es "elegante" en comparación con la solución que habría encontrado (que requiere varias expresiones regulares y una matriz para el almacenamiento temporal). – 10basetom

+0

@ Alan, ¿utilicé su expresión regular tal como está, excepto lo dejé afuera ?: ¿hay otro uso para esto aparte de memorizar el partido? – 10basetom

+0

@ 10basetom: en muchos sabores de expresiones regulares, si usa grupos de captura en la expresión regular dividida, lo que captura se agrega a los resultados junto con los tokens regulares. Pero confieso que ni siquiera estaba pensando en eso en ese momento. Solo estaba siguiendo la regla general: nunca use un grupo de captura si un grupo que no captura puede hacer el trabajo. Cada grupo de captura adicional agrega un poco más a la sobrecarga de recursos, tanto hardware como wetware (es decir, se vuelve más difícil para usted el autor hacer un seguimiento de qué grupo está capturando qué). –

3

Las expresiones regulares no son particularmente buenos en búsqueda de texto equilibrado (es decir, inicio y finalización comillas).

Un enfoque ingenuo sería aplicar repetidamente algo como esto (hasta que ya no coincide):

s/(^[^"]*(?:"[^"]*"[^"]*)*?)"([^",]*),([^"]*)"/$1"$2_$3"/ 

Pero eso no funcionaría con citas escapado. La mejor solución (es decir, más simple, más fácil de leer, y lo más maintanable) es utilizar un analizador de archivos CSV, pasar por todo el campo de valores uno a uno (en sustitución de comas con guiones sobre la marcha), y luego escribir de nuevo a la archivo.

0

Disculpe si no estás usando Python, en la que es el siguiente código. No vi ninguna indicación del idioma que usa. De todos modos, creo que el código es perfectamente comprensible.

import re 

ch = '''0,"section1","(7) Delivery of 'certificate' outside the United States prohibited. 
Since both section 339 of the 1940 statute, 68/ and section 341 of the present law are explicit 
in their statement that the certificate shall be furnished the citizen, only if such individual 
is at the time within the United States, it is clear that the document could not and cannot be 
delivered outside the United States.",http://www.google.com/ 

1,"section2",,http://www.google.com/ 

2,"section3",",,",http://www.google.com/ 
''' 

poto = re.compile('("[^"]+")') 

def comma_replacement(match): 
    return match.group().replace(',','_') 

print poto.sub(comma_replacement , ch) 

Este método mantiene los 2 comas adyacentes en la línea de

1, "section2" ,, http: //www.google.com/

sin cambios. ¿Es lo correcto que quieres?

Cuestiones relacionadas