指定された行数に応じて CSV ファイルを分割するにはどうすればよいですか?

指定された行数に応じて CSV ファイルを分割するにはどうすればよいですか?

私は、LINUX サーバー上に CSV ファイル (約 10,000 行、各行に 300 列) を保存しています。この CSV ファイルを、それぞれ 20 レコードの 500 個の CSV ファイルに分割したいと考えています。(各 CSV ファイルに、元の CSV と同じ CSV ヘッダーがあります)

この変換を支援する Linux コマンドはありますか?

答え1

完全を期すために、いくつかの小さな改善点を以下に示します。

  • ヘッダーを保存できます一度何度も再利用できる
  • sed一時ファイルなしで分割ファイルにヘッダーを挿入することができます

このような:

header=$(head -n 1 file.csv)
tail -n +2 file.csv | split -l 20
for file in x??; do
    sed -i -e 1i$'\\\n'"$header" "$file"
done

$'\\\n'バックスラッシュでエスケープされた NEWLINE 文字があります。この式sedは、$header1 行目の前に挿入することを意味します。

答え2

これで大丈夫だろうそれなしCSV ヘッダー:

tail -n +2 file.csv | split -l 20

次に、各ファイルにヘッダーを追加します。

for file in x*
do
    (head -n 1 file.csv; cat "$file") > "$file".new
    mv "$file".new "$file" # Stolen from @PawanMude's answer
done

答え3

試す:

fn="infile" c=0
{ 
  read header
  split -a 3 -l 3 - "$fn"
  for f in "$fn"???; do
    c=$((c+1))
    printf "%s\n" "$header" | cat - "$f" > "${f%???}-$c" && rm "$f"
  done 
} < $fn

またはawkで試してください:

awk 'NR==1{h=$0; next} !((NR-2)%n){close(f); f=FILENAME "-" ++c; print h>f}{print>f}' n=3 infile

複数行バージョン:

awk '
  NR==1 {
    h=$0
    next
  }
  !((NR-2)%n) {
    close(f)
    f=FILENAME "-" ++c
    print h>f
  }
  {
    print>f
  }
' n=3 infile

答え4

GNU Parallel を使用する:

cat bigfile.csv | parallel -N20 --header : --pipe 'cat > {#}'

各部分でコマンドを実行する必要がある場合は、GNU Parallel も役立ちます。

cat bigfile.csv | parallel -N20 --header : --pipe my_program_reading_from_stdin

cat bigfile.csv | parallel -N20 --header : --pipe --cat my_program_reading_from_a_file {}

関連情報