1

通常、私は次のようなことをします

IFS=','
columns=( $LINE )

ここで、$ LINEは、私が読んでいるcsvファイルの行です。

ただし、カンマが埋め込まれたcsvファイルを処理するにはどうすればよいですか?私は数百ギガのファイルを処理する必要があるので、すべてを迅速に行う必要があります。つまり、行の複数の読み取りやループは絶対にありません(前回試したところ、いくつかの要因が遅くなりました)。

コードの一般的な構造は次のとおりです。

FILENAME=$1
cat $FILENAME | while read LINE
do
    IFS=","
    columns=( $LINE )
    # affect columns changes here
    newline="${columns[*]}"
    echo "$newline"
done

できれば、私は行く何かが必要です

FILENAME=$1
cat $FILENAME | while read LINE
do
    IFS=","
    # code to tell bash to ignore if IFS is within an open quote
    columns=( $LINE )
    # affect columns changes here
    newline="${columns[*]}"
    echo "$newline"
done

ヒントをいただければ幸いです。そうでなければ、私はおそらくこのようなものを処理するために別の言語を使用することに切り替えます。

4

3 に答える 3

2

おそらく埋め込まれたコンマは、これらのCSVファイルの解析中に発生した最初の明らかな問題です。

ポップする可能性のある将来の問題は次のとおりです。

  • 埋め込まれた改行区切り文字
  • 埋め込まれたutf8文字
  • 空白空のフィールドコンマの周りのスペースundef値の特別な扱い

私は一般的に、解析する必要のある形式を解析する(評判の良い)モジュールがある場合は、自作を作成する代わりにそれを使用するという哲学に従う傾向があります

bashにはそのようなものはないと思いますが、Perlにはいくつかあります。私は行きText::CSV_XSます。CIで記述されているため、非常に高速であることが期待されます。

于 2012-12-23T05:30:42.860 に答える
1

これは完全な答えではありませんが、可能なアプローチです。

入力ファイルで発生しない文字を検索します。CSVファイルを解析し、異なる区切り文字を使用して行を標準出力に出力するCプログラムを使用します。そのプログラムを書くことは演習として残されていますが、CSV解析のCソースコードがそこにあると確信しています。Cプログラムの出力をスクリプトにパイプします。

例えば:

FILENAME=$1
new_c_program $FILENAME | while read LINE
do
    IFS="|"
    # code to tell bash to ignore if IFS is within an open quote
    columns=( $LINE )
    # affect columns changes here
    newline="${columns[*]}"
    echo "$newline"
done

$newlineマイナーなポイント:私は;以外の名前を選びます。newline行全体ではなく、行末マーカーを提案します。

もう1つのマイナーなポイント:質問のコードに「役に立たない使用cat」があります。これを置き換えることができます:

cat $FILENAME | while read LINE
do
    ...
done

これで:

while read LINE
do
     ...
done < $FILENAME

しかし、私が提案した架空のCプログラムに置き換えるcat場合でも、パイプが必要です。

于 2012-12-23T05:29:38.720 に答える
1

sedなどを使用して、引用符内のコンマを他のシーケンスまたは句読点に変換できます。引用符の内容を気にしない場合は、元に戻す必要はありません。これはファイル全体で実行できます。

sed 's/\("[^,"]*\),\([^"]*"\)/\1;\2/g' input.csv > intermediate.csv

または各行:

line=$(echo $line | sed 's/\("[^,"]*\),\([^"]*"\)/\1;\2/g')
于 2012-12-23T05:30:30.577 に答える