web-dev-qa-db-ja.com

sedを使用したCSVファイルの変換

一部のデータを特定のツールにインポートできるようにするには、CSVファイルをこの形式から変換する必要があります

"data","data","data data","data","123"

このフォーマットに

data;data;data data;data;123

列に";、または,が含まれることはありませんが、スペースを含めることができます。現在、私は以下を使用しています

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

これは問題なく機能しますが、これをよりエレガントに実行できるかどうか疑問に思います。

  • Sedはその仕事に適した(標準のUnix)ツールですか?
  • 両方の式を1つにマージすることは可能でしょうか?

ご意見ありがとうございます!

7
middus
( tr , ';' | tr -d '"' ) < input.csv > output.csv

Perlを使います

Perl -pe 'tr/,"/;/d' input.csv > output.csv

-しかし、この特定のタスクはsedを超えていません。 2つの式をマージすることはできません。

6
ayrnieu

どちらを好むか(Perl、sed、awk)はあなた次第です。それらはすべて仕事を成し遂げるでしょう。あなたがsedを要求し、他のものが投稿されているので、ここに行きます。これは正規表現のより単純な形式であり、サンプル行で機能します。

$ sed -e 's/"//g; s/,/;/g' infile.csv > outfile.csv

注意してくださいcan各置換の後にセミコロンで2つの式を結合します。 GNU sedv4.1.5でテスト済み。

結合された元の式は次のとおりです。

$ sed -e 's/","/;/g; s/"//g' infile.csv > outfile.csv

2つの置換をマージすることは可能であると私は合理的に確信しています。それが手に負えないものになるかどうかはわかりません。結果は、上部のスクリプトよりもはるかに読みにくくなると確信しています。私が何かを思いついた場合(または他の誰かがコメントに加わった場合)、ここに追加します。

5
quack quixote

レコードを扱っているので、awkの方が理にかなっています。とはいえ、フィールド区切り文字は多少可変であるため、CSVはあまり得意ではありません。ただし、すべてのフィールドが二重引用符で囲まれていることが確実な場合は、次のように機能します。

awk -F'","' 'BEGIN {OFS=";"} { gsub(/(^")|("$)/, ""); $1=$1; print }'

これにより、awkの入力フィールドセパレーターが「","」に設定されます(二重引用符の内側のセットを含む)。これは、gsub関数で削除される先頭と末尾の二重引用符を処理する必要があることを除いて、ほとんど機能します。 $1=$1は、BEGINブロックで;として定義された新しい出力フィールド区切り文字を使用してレコードを再コンパイルするように強制します。次に、printはレコード全体を出力します。

これは少し整頓されています:

awk -F '(^")|(",")|("$)' 'BEGIN {OFS=";"} { $1=$1; print }'

入力フィールド区切り文字を、レコードの最初と最後に二重引用符を含む正規表現に設定しますが、空の開始フィールドと終了フィールドも出力します。後続のフィールドを簡単に取り除くことができます。

awk -F '(^")|(",")|("$)' 'BEGIN {OFS=";"} { NF=NF-1; $1=$1; print }'

NFはフィールドの数であり、最後のフィールドから1つ減らします。しかし、私は最初のフィールドを切り落とす方法を考えることができません。

ただし、入力に常に5つのフィールドがあることがわかっている場合は、次のようにすることができます。

awk -F '(^")|(",")|("$)' 'BEGIN {OFS=";"} { print $2,$3,$4,$5,$6 }'

これにより、$1=$1構造が削除されることに注意してください。これは、(暗黙の)$ 0を出力する場合にのみ必要です。

そうは言っても、私はおそらくPerlと利用可能な多くの CPAN上のCSVモジュール の1つを使用することになります。

4
wfaulk