web-dev-qa-db-ja.com

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

LINUXサーバーにCSVファイル(約10,000行、各行に300列)を保存しました。このCSVファイルをそれぞれ20レコードの500のCSVファイルに分割したいと思います。 (それぞれが元のCSVに存在するものと同じCSVヘッダーを持っています)

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

2
Pawan Mude

完全を期すために、ここにいくつかのマイナーな改善があります:

  • ヘッダーを保存してonceそして何度も再利用できます
  • 一時ファイルなしで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式の意味:insert $header1行目の前。

2
janos

これでうまくいくはずですなし 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
1
l0b0

試してみてください:

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
1
Scrutinizer

下記のPOST)を使用してこれを解決する最良の方法:

解決策

    tail -n +2 file.txt | split -l 4 - split_
for file in split_*
do
    head -n 1 file.txt > tmp_file
    cat $file >> tmp_file
    mv -f tmp_file $file
done
0
Pawan Mude

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 {}
0
Ole Tange