Reemplazo de coma si se encuentra entre comillas dobles en un archivo CSV usando sed

Reemplazo de coma si se encuentra entre comillas dobles en un archivo CSV usando sed

Tengo un archivo CSV que necesito cargar en una tabla MySQL. Me baso en identificar las columnas que terminan por el ,carácter. Por eso es importante que ,no aparezca en otro lugar que no sea como separador de columnas.

Encontré algunas filas que contienen una columna con ,comillas dobles internas. por ejemplo una línea como esta:

12,"name, brand - something, something",age,sex,,,,"name, brand - something, something, something",,,,,

Necesita convertirse a:

12,name; brand - something; something,age,sex,,,,name; brand - something; something; something,,,,,

Como puede ver, reemplacé las ,comillas dobles internas ;para que cuando cargue el archivo en MySQL las ,comillas dobles internas no se consideren como un separador, ya que ya no lo son ,. También eliminé las comillas dobles "porque no son necesarias.

Intenté automatizar esto para cada fila de mi archivo CSV usando sed de la siguiente manera:

sed -e 's/"\*,\*"/"\*;\*"/g' -e 's/"//g' input.csv > output.csv

Pero el resultado no reemplazó los ,que vienen entre comillas dobles con ;. Sólo eliminó las comillas dobles:

12,name, brand - something, something,age,sex,,,,name, brand - something, something, something,,,,,

Respuesta1

Los archivos csv pueden ser muy complicados. Es posible que termine teniendo una cita de escape en algún lugar de la línea y la expresión regular para manejarla sería ilegible y propensa a errores.

Yo sugeriría una herramienta comocvkito un pequeño script en perl o python. Este programa rápidamente elaborado en Python debería hacerlo:

import csv

with open('input.csv',mode='r') as csv_file:
   csv_reader = csv.reader(csv_file)
   for row in csv_reader:
       print (',').join([f.replace(',',';') for f in row])

Respuesta2

Como ya lo mencionó @steeldriver, mysqlprobablemente sepa cómo manejar eso si usa elopciones correctas, pero FWIW puedes hacer eso con awk:

awk -v RS='"' -v ORS= 'NR % 2 || gsub(/,/,";") || 1'

12,name; brand - something; something,age,sex,,,,name; brand - something; something; something,,,,,

O, manteniendo las comillas adjuntas:

awk -v RS='"' -v ORS= '{if(NR % 2) print; else{gsub(/,/,";");print RS $0 RS}}'

12,"name; brand - something; something",age,sex,,,,"name; brand - something; something; something",,,,,

Esto está usando el mismo truco queaquí, sólo revertido: en lugar de modificar la piezaafueralas comillas, estoy modificando la parteadentroLas citas.

Respuesta3

La mejor respuesta que encontré es usar MySQL agregando esta línea:

OPTIONALLY ENCLOSED BY '"'

Así, por ejemplo, la consulta de carga se ve así:

LOAD DATA INFILE 'filename.csv' INTO TABLE table_name 
  FIELDS TERMINATED BY ',' 
  OPTIONALLY ENCLOSED BY '"'
  IGNORE 1 LINES;

información relacionada