PerlでCSVファイルやTSVファイルを列マージする
前回のエントリでは、csvファイルのある列を境にしてのファイル分割をしましたが、
今回は逆に2つに分かれているファイルを1つにマージする処理をPerlで書いてみました。
※ハッキリ言って、たいした内容じゃないです。
前回のエントリ:PerlでCSVファイルやTSVファイルを列で分割する
データサンプル
base.csv(元ファイル その1)
Key | Deta2 |
---|---|
1 | A2 |
2 | B2 |
3 | C2 |
4 | D2 |
5 | E2 |
new.csv(マージされたファイル)
Key | Deta1 | Deta2 | Deta3 |
---|---|---|---|
1 | A1 | A2 | A3 |
2 | B2 | ||
3 | C1 | C2 | C3 |
4 | D2 | ||
5 | E1 | E2 | E3 |
Perlで実装
今回もテキストファイルということでPerlで実装してみました。
処理の手順としては、
- 追加する側のファイル(行)を読み込み
- 読み込んだデータ(行)の1列目をキーとしてハッシュ配列を作成
- 追加される側のファイル(行)を読み込み
- 読み込んだデータ(行)の1列目をキーとして2.で作成したハッシュ配列からデータを取得
- マージ後の配列を作成しファイルに出力
といった感じになります。
ポイントとしては、ハッシュを使っているところくらいです。
今回の例の場合だと、base.csvに対してadd.csvの内容を追加する形になります。
base.csvとadd.csvに同じキーの行があれば、データが追加されますが、
add.csvにしかない行は出力(追加)されません。
base.csvにしか無い行は、そのまま(データ追加されずに)出力されます
以下がサンプルコードになります。
もう少しスマートな方法があるかもしれませんが、まずはこれでしばらく使ってみます。
サンプルソースコード(全部)
#!/usr/local/bin/perl # # merge_csv.pl # use strict; use warnings; my $delimiter = ','; my %hash; # FIle Open (add.csv) open( IN, 'add.csv') or die $!; while(<IN>){ s/\r\n|\n|\r//g; my @row = split/$delimiter/; # 1列目の項目をキーとしてハッシュに格納 $hash{"$row[0]"} = \@row; } close(IN); # FIle Open (base.csv & new.csv) open( IN, 'base.csv') or die $!; open( OUT, '> new.csv'); while(<IN>){ s/\r\n|\n|\r//g; my @row_base = split/$delimiter/; # 1列目の項目をキーとしてハッシュからデータを取得 my @row_add = $hash{"$row_base[0]"} ? @{$hash{"$row_base[0]"}} : (); my @row_new = (); # new.csv用に新しい配列にデータをセット $row_new[0] = $row_base[0]; $row_new[1] = $row_add[1] ? $row_add[1] : ''; $row_new[2] = $row_base[1]; $row_new[3] = $row_add[2] ? $row_add[2] : ''; print OUT join("$delimiter", @row_new) . "\n"; } close(OUT); close(IN);