1m行の巨大なCSVファイルがあります。このファイルを小さいファイルに分割する方法はあるかと思っていましたが、すべてのファイルの最初の行(CSVヘッダー)を保持しています。
split
は非常に高速ですが、非常に制限されています。 .csv
のようなファイル名にサフィックスを追加することはできません。
split -l11000 products.csv file_
bash
だけでこのタスクを実行する効果的な方法はありますか? 1行のコマンドはすばらしいでしょう。
この質問の答えは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}
_:エントリをファイルに書き込みます。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}."