sed を使用して CSV ファイル内の二重引用符内のカンマを置換する

sed を使用して CSV ファイル内の二重引用符内のカンマを置換する

MySQL テーブルにロードする必要がある CSV ファイルがあります。列の終わりを文字で識別することに頼っています。そのため、列の区切り以外の場所に,が表示されないようにすることが重要です。,

二重引用符で囲まれた列を含む行がいくつか見つかりました,。たとえば、次の行です。

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 でファイルをロードするときに、,内部の二重引用符はもはや区切り文字ではないため、区切り文字として認識されません。,また、二重引用符"は不要なので削除しました。

次のように sed を使用して、CSV ファイルのすべての行に対してこれを自動化しようとしました。

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 ファイルは非常に扱いにくい場合があります。行のどこかにエスケープされた引用符が含まれ、それを処理する正規表現が判読不能になり、エラーが発生しやすくなります。

私は次のようなツールをお勧めしますcskit さんまたは、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;

関連情報