Замена запятой, если она находится внутри двойных кавычек в CSV-файле с помощью sed

Замена запятой, если она находится внутри двойных кавычек в CSV-файле с помощью sed

У меня есть CSV-файл, который мне нужно загрузить в таблицу MySQL. Я полагаюсь на идентификацию конца столбцов по символу ,. Вот почему важно, чтобы ,не появлялся нигде, кроме как в качестве разделителя столбцов.

Я нашел несколько строк, содержащих столбец с ,двойными кавычками внутри. Например, такую ​​строку:

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

Необходимо преобразовать в:

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

Как видите, я заменил ,внутренние двойные кавычки на ;, чтобы при загрузке файла в MySQL ,внутренние двойные кавычки не считались разделителем, поскольку они ,больше им не являются. Я также удалил двойные кавычки, "поскольку они не нужны.

Я попытался автоматизировать это для каждой строки в моем CSV-файле с помощью sed следующим образом:

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

Но результат не заменил , ,которые находятся внутри двойных кавычек, на ;. Он только удалил двойные кавычки:

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

решение1

Файлы csv могут быть очень сложными. Вы можете получить экранированную кавычку где-то в строке, и регулярное выражение для ее обработки будет нечитаемым и подверженным ошибкам.

Я бы предложил такой инструмент, какcvskitили небольшой скрипт на perl или python. Эта быстро созданная программа на python должна это сделать:

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])

решение2

Как уже упоминал @steeldriver, mysqlвероятно, знает, как с этим справиться, если использоватьправильные варианты, но кстати, это можно сделать и с помощью awk:

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

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

Или, сохраняя прилагаемые кавычки:

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",,,,,

Здесь используется тот же трюк, что издесь, только откат: вместо изменения частиснаружикавычки, я изменяю частьвнутрицитаты.

решение3

Лучший ответ, который я нашел, — это использование самого MySQL путем добавления следующей строки:

OPTIONALLY ENCLOSED BY '"'

Например, запрос на загрузку выглядит так:

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

Связанный контент