複数の.csvファイルの内容を単一の.csvファイルにマージする

複数の.csvファイルの内容を単一の.csvファイルにマージする

複数の.csvファイルの内容を1つの.csvファイルにマージするスクリプトを作成したいと思います。つまり、他のすべてのファイルの列を最初のファイルの列に追加します。これを行うために「for」ループを試しましたが、続行できません。

Linuxでこれを行う方法を知っている人はいますか?

答え1

これを達成する最も簡単な方法は、次のコマンドを入力することです。

cat *csv > combined.csv

このファイルには、前述のすべてのcsvファイルの内容が含まれています。

答え2

awk '(NR == 1) || (FNR > 1)' *.csv > 1000Plus5years_companies_data.csv

答え3

使用paste

paste -d ',' file1.csv file2.csv ... fileN.csv

答え4

@csv以下は、コマンドラインで指定された各ファイルの各行を読み取り、それを配列()の要素に追加するPerlスクリプトです。入力がなくなったら、各要素を印刷します@csv

ファイルは.csvコマンドラインにリストされている順序で追加されます。

警告する:このスクリプトは次のことを前提としています。すべての入力ファイルの行数は同じです。。ファイルの行数が他のファイルと異なる場合、出力を使用できない可能性があります。

#!/usr/bin/perl

use strict;

my @csv=();

foreach (@ARGV) {
  my $linenum=0;

  open(F,"<",$_) or die "couldn't open $_ for read: $!\n";

  while (<F>) {
    chomp;
    $csv[$linenum++] .= "," . $_;
  };

  close(F);
};

foreach (@csv) {
  s/^,//;   # strip leading comma from line
  print $_,"\n";
};

次の入力ファイルが与えられた場合:

==> 1.csv <==
1,2,3,4
1,2,3,4
1,2,3,4
1,2,3,4

==> 2.csv <==
5,6,7,8
5,6,7,8
5,6,7,8
5,6,7,8

==> 3.csv <==
9,10,11,12
9,10,11,12
9,10,11,12
9,10,11,12

次の出力が生成されます。

$ ./mergecsv.pl *.csv
1,2,3,4,5,6,7,8,9,10,11,12
1,2,3,4,5,6,7,8,9,10,11,12
1,2,3,4,5,6,7,8,9,10,11,12
1,2,3,4,5,6,7,8,9,10,11,12

さて、今ここまで読んだので、これがしないことをしないことをpaste -d, *.csv認めなければならない時です。それでは、あえてPerlを使用するのはなぜですか? paste非常に柔軟性がありません。データが作業に完全に適している場合はpaste問題ありません。仕事に最適で非常に高速です。そうでなければそれはあなたに全く役に立たない。

このようなPerlスクリプトは、いくつかの方法で改善することができます(たとえば、@csvファイルあたりのフィールド数を計算し、欠落している各ファイルに正しい数の空のフィールドを追加するか、少なくとも異なる長さと終了エラーを検出して、さまざまな長さのファイル行を処理)。しかし、より複雑なマージが必要な場合、これは合理的な出発点になります。

しかし、これは非常に単純なアルゴリズムを使用し、すべての入力ファイルの内容全体をメモリ(in @csv)に一度に保存します。サイズがそれぞれ最大数MBに達する最新システムのファイルについては、これは無理ではありません。ただし、大容量の.csvファイルを処理する場合、より良いアルゴリズムは次のとおりです。

  • 読み込む入力はまだ残っていますが、すべての入力ファイルを開きます。
    • 各ファイルから1行を読む
    • 行を追加(@ARGV順)
    • 追加行印刷

関連情報