大量のCSVファイルのデータをソート(sort:並べ替え)するのは、本来はデータベース側で行うことであって、Perlで行うことではありません。しかし、実際にはPerlで行うことになる場合もあります。そうした場合にPerlでどのような対応を行うかについて説明していきます。ここで大量のCSVファイルとは、[2-4-2.CSVファイルの文字列型昇順ソート]で並べ替える場合は100万件以上、[2-4-3.CSVファイルの文字列型・数値型/昇順・降順ソート(その1)]で並べ替える場合は10万件以上のCSVデータが1つのファイルに入っていることを前提にしています。これ以上のデータを並べ替える(ソートする)には以下の手順で行います。
まず、並べ替えの方式のどれかを確認します。
1の場合は、以下の手順で行います。
2の場合は、以下の手順で行います。
実際に応用する場合は、入出力データのファイル名を変更し、「@sortkey = (0)」の部分を変更します。この例では、1番目の項目を第1キーとして並べ替えるように指定しています。Perlでは、配列のインデックスは「0」から開始されますので、1番目の項目を「0」、2番目の項目を「1」として指定することに注意してください。
下記の例では、フィールドを「"」(ダブルクォーテーションつき)で囲み、それぞれのデータを「,」(カンマ)で区切っている形式を前提としているため、
$tmp = $line1; $tmp =~ s/(?:\x0D\x0A|[\x0D\x0A])?$/,/; @in1 = map {/^"(.*)"$/ ? scalar($_ = $1, s/""/"/g, $_) : $_} ($tmp =~ /("[^"]*(?:""[^"]*)*"|[^,]*),/g);
としていますが、フィールドを「"」(ダブルクォーテーションつき)で囲まずに、それぞれのデータを「,」(カンマ)で区切っている、いわゆる「CSV2形式」であれば、以下のようにすることができます。
@in1 = split(",",$line1,-1);
また、タブ区切りであれば、以下のようにすることができます。
@in1 = split("\t",$line1,-1);
# keycount.pl # 内容 :CSV形式のファイルのソート(並べ替え)キーごとの # 件数と累計件数をカウントする。 # Copyright (c) 2011 Mitsuo Minagawa, All rights reserved. # (minagawa@fb3.so-net.ne.jp) # 使用方法 : c:\>perl keycount.pl # open(IN1,"input.txt"); open(OUT1,">output.txt"); # ソート(並べ替え)キーの入っている項目番号 @sortkey = (0); # ソート(並べ替え)用のキー $key = undef; # ソート(並べ替え)用のキーと件数をセットするハッシュ %sort_record = (); # 累計件数 $total_ctr = 0; # ソート(並べ替え)キーとなる項目番号から # ソート(並べ替え)キーとなる文字列を作っておく while ($line1 = <IN1>) { # 対象ファイルをカンマで分解する chomp($line1); $tmp = $line1; $tmp =~ s/(?:\x0D\x0A|[\x0D\x0A])?$/,/; @in1 = map {/^"(.*)"$/ ? scalar($_ = $1, s/""/"/g, $_) : $_} ($tmp =~ /("[^"]*(?:""[^"]*)*"|[^,]*),/g); # @in1 = split("\t",$line1,-1); # ソート(並べ替え)キーとなる項目内容をタブをはさんで連結してキーとする foreach $sortno (@sortkey) { $key .= $in1[$sortno] . "\t"; } chop($key); # ソート(並べ替え)キーに該当するキーがあれば、件数を加算する。 if ($sort_record{$key}) { $sort_record{$key} += 1; } # 新たなソート(並べ替え)キーに該当する場合は、初期値1をセットする。 else { $sort_record{$key} = 1; } $key = undef; } # ハッシュのキーをソート(並べ替え)し、キー順にレコードを出力する foreach $recno (sort keys %sort_record) { $total_ctr += $sort_record{$recno}; $out1 = join("\t",$recno,$sort_record{$recno},$total_ctr); print OUT1 "$out1\n"; } close(IN1); close(OUT1);
ccc,5555 aaa,7777 bbb,9999 aaa,1111 bbb,3333 bbb,4444 aaa,5555 ccc,1111
aaa 3 3 bbb 3 6 ccc 2 8