複数の.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順)
- 追加行印刷