1

いくつかのCSVを処理するbashファイルがあります。一部の入力CSVが正しくフォーマットされていないため、sedで修正したいと思います。引用符はのようにエスケープされ、のようにエスケープ\"されない""ので、これを変更するためにsedを呼び出します。コマンドラインでは、これは完全に機能します。

sed -i 's/\\"/""/gi' input.csv

しかし、bashスクリプト内では、これは何もしないようです。引用符とエスケープシーケンスと関係があると思いますが、解決策は何ですか?

4

2 に答える 2

5

それを機能させるには、エスケープ文字をエスケープする必要があります\

$ echo 'bla;\"bli bli\";otherbla' | sed -e 's/\\\"/""/g'
bla;""bli bli"";otherbla

bashスクリプトの場合、CSVファイルから読み取った行がsedに渡すときに正しく引用符で囲まれていることを確認する必要があります。CSVファイルの例とファイルからの読み取り方法を教えてください。

を使用しcat file | while readて、問題の例を次に示します。

$ cat test.csv
bla;\"bli bli\";otherbla
ble;""bli bli"";otherbla
bli;\"blo\";otherbla

$ cat test.sh
#!/bin/bash

cat test.csv | while read line;
do echo "$line" | sed -e 's/\\\"/""/g'
done

$ ./test.sh
bla;"bli bli";otherbla
ble;""bli bli"";otherbla
bli;"blo";otherbla

1つの解決策は、スクリプトでechoを使用せずに、ファイルで直接sedを使用し、結果のcsvを新しいファイルに保存することです。

$ sed -e 's/\\\"/""/ig' test.csv > test-tmp.csv
$ cat test-tmp.csv
bla;""bli bli"";otherbla
ble;""bli bli"";otherbla
bli;""blo"";otherbla

次に、コメントで指摘されているように、引用符で囲まれたフィールドの混乱や誤った置換を回避するために、\2つのsed式を使用し、フィールドセパレーターを含めて、フィールドセパレーターの前後のみ\"を置換するようにします(私の例では、フィールドセパレータは)ですが、これは、次の行などのフィールドの最後の文字として;一重引用符で囲まれたフィールドを考慮していません。\blo

$ cat test.csv
bla;\"bli bli\";otherbla
ble;""bli bli"";otherbla
bli;\"blo\";otherbla
blo;"bli bli\";otherbla
blu;""bli bli\"";otherbla

$ sed -e 's/;\\\"/;""/ig' -e 's/\\\";/"";/ig' test.csv
bla;""bli bli"";otherbla
ble;""bli bli"";otherbla
bli;""blo"";otherbla
blo;"bli bli"";otherbla
blu;""bli bli\"";otherbla

複数のsedコマンドがある場合は、スクリプトに入れることができます。同じように機能します。

$ cat s.sed 
s/\\\"/""/g

それを使用する:

$ echo 'bla;\"bli bli\";otherbla' | sed -f s.sed 
bla;""bli bli"";otherbla

sed -f s.sed test.csv > test-tmp.csv
于 2012-10-05T11:48:05.643 に答える
3

フィールドの1つが合法的に\文字で終わっている場合を考えましたか?CSVファイルの引用符で囲まれた表現は、円記号とそれに続く引用符で終わります。あなたやThomasのようなsedソリューションはそれを覆い隠します。

これが、sedが引用符で囲まれたcsvを操作するための間違ったツールである理由です。一部の問題は、適切な言語(awk、Perlなど)でのみ再帰的に解決できます。

于 2012-10-05T12:04:48.347 に答える