web-dev-qa-db-ja.com

CSVファイルを小さいファイルに分割しますが、ヘッダーは保持しますか?

1m行の巨大なCSVファイルがあります。このファイルを小さいファイルに分割する方法はあるかと思っていましたが、すべてのファイルの最初の行(CSVヘッダー)を保持しています。

splitは非常に高速ですが、非常に制限されています。 .csvのようなファイル名にサフィックスを追加することはできません。

split -l11000 products.csv file_

bashだけでこのタスクを実行する効果的な方法はありますか? 1行のコマンドはすばらしいでしょう。

7
neisantos

この質問の答えはyesです。これはAWKで可能です。

ヘッダーを念頭に置き、残りをすべて_filename.00001.csv_の形式のファイル名で出力するのが目的です。

_awk -v l=11000 '(NR==1){header=$0;next}
                (NR%l==2) { 
                   c=sprintf("%0.5d",c+1); 
                   close(file); file=FILENAME; sub(/csv$/,c".csv",file)
                   print header > file
                }
                {print $0 > file}' file.csv
_

これは次のように機能します。

  • _(NR==1){header=$0;next}_:レコード/行が最初の行である場合、その行をheaderとして保存します。
  • _(NR%l==2){...}_: _l=11000_レコード/行を書き込むたびに、新しいファイルへの書き込みを開始する必要があります。これは、レコード/行番号のモジュロが2に達するたびに発生します。これは、行2、2 + l、2 + 2l、2 + 3l、....そのような行が見つかったら、次のようにします:
    • c=sprintf("%0.5d",c+1)カウンターを1つ増やし、_000xx_として出力します
    • close(file)先ほど作成したファイルも閉じます。
    • file=FILENAME; sub(/csv$/,c".csv",file)新しいファイル名を定義します
    • _print header > file_:ファイルを開き、ヘッダーをそのファイルに書き込みます。
  • _{print $0 > file}_:エントリをファイルに書き込みます。
20
kvantour

GNU splitを使用して分割するfile.csv

export inputPrefix='file' parts=16 && split --verbose -d -n l/${parts} --additional-suffix=.csv --filter='([ "$FILE" != "${inputPrefix}.00.csv" ] && head -1 "${inputPrefix}.csv" ; cat) > "$FILE"' "${inputPrefix}.csv" "${inputPrefix}."
1
nzkeith