CSVファイルを読み込んで、キーが重複しているレコードを除去して、キーがユニークなレコードだけを出力するスクリプトです。同じキーを持つデータが1件しかない場合のみ出力するようにしています。
実際に応用する場合は、入出力データのファイル名などを変更してください。
なお、[3-2-1.キーの重複したデータを1つにする]と異なり、入力データはキー順に並べ替えておく必要はありません。
# single_hash.pl
# 内容 : 重複データ除去
# 前提 : 重複チェックしたいキーであらかじめソートしておく必要はない。
# Copyright (c) 2013 Mitsuo Minagawa, All rights reserved.
# (minagawa@fb3.so-net.ne.jp)
# 使用方法 : c:\>perl single_hash.pl
#
# 出力用ハッシュ
my %out1;
# マスタデータをハッシュに入れる
open(IN1,"double.txt");
while($line1 = <IN1>) {
chomp($line1);
#---区切り文字により、処理を変更する----------
#タブ区切りのとき
# @in1 = split("\t",$line1);
#カンマ区切りのとき
my $tmp = $line1;
$tmp =~ s/(?:\x0D\x0A|[\x0D\x0A])?$/,/;
@in1 = map {/^"(.*)"$/ ? scalar($_ = $1, s/""/"/g, $_) : $_}
($tmp =~ /("[^"]*(?:""[^"]*)*"|[^,]*),/g);
#-----------------
$in1_key = $in1[0];
# ハッシュのキーが存在しない場合
unless (exists $out1{$in1_key}) {
@double = ();
push(@double,$line1);
$out1{$in1_key} = [@double];
}
}
close(IN1);
open(OUT1,">single_only.txt");
# ハッシュのキーをソートして出力する
foreach my $key (sort keys %out1) {
# キーと件数をカンマ区切りで結合し、出力する
print OUT1 join("\n", @{$out1{$key}})."\n";
}
close(OUT1);
それでは、スクリプトの解説を個別に行っていきましょう。
重複しないデータのみセット
# ハッシュのキーが存在しない場合
unless (exists $out1{$in1_key}) {
@double = ();
push(@double,$line1);
$out1{$in1_key} = [@double];
}
重複しているかどうかをハッシュを使って判定しています。ハッシュのキーが存在していない場合は重複していないものとして、データをハッシュにセットします。
データ出力
# ハッシュのキーをソートして出力する
foreach my $key (sort keys %out1) {
# キーと件数をカンマ区切りで結合し、出力する
print OUT1 join("\n", @{$out1{$key}})."\n";
}
ハッシュのキー順に並べ替えて、ハッシュのデータを出力します。
その他注意すべきこと
その他、注意すべき点は入力データがタブ区切りなどの場合とキーが複数ある場合の処理です。
1.入力データがタブ区切りの場合
上記のスクリプトはCSV2形式以外の引用符(")を使用する場合を含め、あらゆるCSVファイルに対応できるようになっていますが、入力データがタブ区切りの場合は
my $tmp = $line1;
$tmp =~ s/(?:\x0D\x0A|[\x0D\x0A])?$/,/;
@in1 = map {/^"(.*)"$/ ? scalar($_ = $1, s/""/"/g, $_) : $_}
($tmp =~ /("[^"]*(?:""[^"]*)*"|[^,]*),/g);
上記の部分を
@in1 = split("\t",$line1,-1);
と変更します。
2.キーが複数の項目から成り立っている場合
「$in1_key = $in1[0];」の部分を
$in1_key = $in1[0].$in1[1].$in1[2];
のように変更します(文字列の連結は「.」(ピリオド)を使う)。
aaa,1
aaa,2
aaa,3
bbb,1
ccc,1
ccc,2
ddd,1
ddd,2
ddd,3
ddd,4
eee,1
fff,1
ggg,1
hhh,1
hhh,2
hhh,3
aaa,1
bbb,1
ccc,1
ddd,1
eee,1
fff,1
ggg,1
hhh,1