CSVファイルを読み込んで、キーが重複しているレコードを除去して、キーがユニークなレコードだけを出力するスクリプトです。前レコードと異なるキーを持つ場合のみ出力するようにしています。
実際に応用する場合は、入出力データのファイル名などを変更してください。また、入力データはキー順に並べ替えてあることが前提となっています。Perlを利用して並べ替えを行う場合については、[2-4.ソート(並べ替え)処理]を参照してください。
なお、同様の処理を行う[3-2-4.ハッシュを使って、キーの重複したデータを1つにする]については、入力データをキー順に並べ替えておく必要はありません。
# single.pl # 内容 : 重複データ除去 # 前提 : 重複チェックしたいキーであらかじめソート(並べ替え)しておく。 # Copyright (c) 2002-2011 Mitsuo Minagawa, All rights reserved. # (minagawa@fb3.so-net.ne.jp) # 使用方法 : c:\>perl single.pl # # 初期値設定 $low_value = pack("h8","00000000"); #low-value $in1_key = $low_value; #入力キー $sv_key = $low_value; #1件前の保存キー open(IN1,"double.txt"); open(OUT1,">single.txt"); while ($line1 = <IN1>) { chomp($line1); my $tmp = $line1; $tmp =~ s/(?:\x0D\x0A|[\x0D\x0A])?$/,/; @in1 = map {/^"(.*)"$/ ? scalar($_ = $1, s/""/"/g, $_) : $_} ($tmp =~ /("[^"]*(?:""[^"]*)*"|[^,]*),/g); $in1_key = $in1[0]; if ($in1_key ne $sv_key) { $out1 = join(",",@in1); print OUT1 "$out1\n"; } $sv_key = $in1_key; } close(IN1); close(OUT1);
スクリプトは「$sv_key」に1件前のキーを保存しておき、入力したキーと比較して、異なっていたら出力しているだけの簡単なものになっています。「$sv_key」には初期値として「$low_value」をセットしていますが、「undef」にしても可能です。
その他注意すべきこと
その他、注意すべき点は入力データがタブ区切りなどの場合とキーが複数ある場合の処理です。
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