• ベストアンサー
※ ChatGPTを利用し、要約された質問です(原文:perlでCSVをソートする方法について)

perlでCSVをソートする方法について

kumozの回答

  • kumoz
  • ベストアンサー率64% (120/185)
回答No.1

out.txt を作成するまでは、よくできているいるように思います。その後の細分化しながらのグループ分けは、あまり有効的なやり方ではありません。カラム37番目 (コード中も 37 になっているので、0 から数えた?) が整数であるとすると、最大 50 種類で平均しても1種類で 600 行にもなってしまうからです。ソート対象は37番目のカラムのみのようですので、ソート済みの out.txt の行を順に 11111, 11112, 11121, ..., 34232, 34241, 34242 に割り当てたほうが簡単に済むように思います。 while (my $line = <$fh>) { ... if (eof) { $groupGyousuu = int($. / 192); $amari = $. % 192; } } 最初の while ループの最終行でグループ行数と余りの行を算出しておきます。次のコードでは、フラグをファイ名に含めてあります。行に入れる場合は、コメントアウトしてある行を参考にしてみてください。(なお、余りの行がない場合、余分な空ファイルが作られてしまいますが、繁雑になるので除外のコードを入れてありません。) my ($count, $idx_amari, $flag) = (0, 0, '11111'); open IN, '<:encoding(cp932)', "$dir/out.txt" or die "Can't open: $!"; open OUT, '>:encoding(cp932)', "$dir/out$flag.txt" or die "Can't open: $!"; while (my $line = <IN>) { # substr($line, index($line, ','), 0) = ',' . join(',', split //, $flag); print OUT $line; $count++; if ($count == $groupGyousuu + ($idx_amari < $amari ? 1 : 0)) { close OUT; $flag = next_flag($flag); $idx_amari++; open OUT '>:encoding(cp932)', "$dir/out$flag.txt" or die "Can't open: $!"; } } close OUT; sub next_flag { my @temp = split //, $_[0]; my @limit = (3, 4, 2, 4, 2); foreach my $i (reverse 0 .. 4) { if ($temp[$i] < $limit[$i]) { $temp[$i]++; return join('', @temp); } else { $temp[$i] = 1; } } }

関連するQ&A

  • CSVデータ「","」と「,」混在読取り出来ず

    ソート機能がうまく動作しなくなりました。 CSVが以下のようなものとなったときにソートがうまく動作しなくなってしまいました。 CSVデータの区切りが「","」と「,」の混在で区切られてます。 (ここから) データa "山田","埼玉県","男性" "田中","埼玉県","男性" "井上","栃木県","女性" "志村","千葉県","男性" (ここまで) だったり (ここから) データb 1,山田,埼玉県,男性,50,"予算2,000円",0 2,田中,埼玉県,男性,36,予算なし,0 3,井上,栃木県,女性,30,予算100円,0 4,志村,千葉県,男性,27,"予算300,000円",0 (ここまで) このようなテータの時もあります。 以前のアドバイスをもとに以下のように作成いたしました。 (ここから) while (my $line = <$ifh>) { if ($socnt == 0 ){$socnt++;next;} my $key = (split /\",\"/, $line)[$ccsv]; push @{$sorted{$key}}, $line; if (@{$sorted{$key}} == 1000) { open OUT, ">>./$key.tmp" or die "Can't open: $!"; print OUT @{$sorted{$key}}; close OUT; @{$sorted{$key}} = (); } } (ここまで) この場合だと my $key = (split /\",\"/, $line)[$ccsv]; データaはうまくいくのですが、データbがうまくソートが動作いたしません。 my $key = (split /,/, $line)[$ccsv]; ではデータbはうまくいくのですが、データaうまくソートが動作いたしません。 条件式で混在認識方法があるかと思っている(ないかもしれませんが、わたしには分かりません)ので質問いたしました。 ご教授いただけますと幸いです。 よろしくお願いします。

    • ベストアンサー
    • Perl
  • プログラムの高速化

    いつもお世話になっております.以下のプログラムをできるだけ高速化したいと思います. use warnings; use strict; my $dirname = '.'; opendir(DIR, $dirname) or die "$dirname: $!"; while (my $dir = readdir(DIR)) { next unless (-f $dir); next unless ($dir =~ /\.txt$/); open(FILE, $dir) or die "$dir: $!"; while (my $line = <FILE>) { my ($a,$b,$c,$d,$e,$f) = split( /,/ , $line ); my $name = $a.",".$b; open(NEWFILE, ">> ./out/$name.txt") or die "$dir: $!"; print NEWFILE $line; close(NEWFILE); } } close(FILE); closedir(DIR); やっていることは,ディレクトリ内のテキストファイルを読み込んでいって,splitでカンマ区切りにした,$a,$bをファイル名として下のディレクトリのoutに保存していくというものです. ファイル数が数千あり,各ファイルも数千行となるため,このソースを高速化する方法はありますでしょうか.ご回答よろしくお願いします.

    • ベストアンサー
    • Perl
  • 一つのテキストファイルと複数のファイルの結合

    よろしくお願いします.ディレクトリ内の一つのテキストファイル(joint.txt)と複数のファイルの結合を行ごとに隣へ結合するプログラムを作成しています.ここで以下のプログラムを作成したのですが,うまくいかないため,誤っている部分をご指摘願えないでしょうか. my $dirname = '.'; opendir(DIR, $dirname) or die "$dirname: $!"; while (my $dir = readdir(DIR)) { next unless (-f $dir); next unless ($dir =~ /\.txt$/); open(FILE, $dir) or die "$dir: $!"; open(FILE2,"joint.txt"); my @file = <FILE>; my @file2 = <FILE2>; close(FILE); close(FILE2); foreach my $line (@file) { foreach my $line2 (@file2) { chomp $line2; $line = "$line2.",".$line"; } } open(NEWFILE, "> $dir") or die "$dir: $!"; print NEWFILE @file; print NEWFILE @file2; close(NEWFILE); } closedir(DIR);

    • ベストアンサー
    • Perl
  • [perl5.8] SJISで出力したはずのファイルにutf8フラグが

    1)SJISで以下の2行を含むファイルを作成し、   sjis.txtという名前で保存します。 "ホツカイドウ" "北海道" 2)SJISで以下のスクリプトを作成します。 #=== one.pl === use encoding 'Shift_JIS'; use open IN => ":encoding(Shift_JIS)"; use open OUT => ":encoding(Shift_JIS)"; my $infile = 'sjis.txt'; my $outfile = 'sjis2.txt'; open(IN, "<$infile"); @lines = <IN>; close(IN); open(OU, ">$outfile"); print OU @lines; close(OU); 3)SJIJSで以下のスクリプトを作成します #=== two.pl === use encoding 'Shift_JIS'; use open IN => ":encoding(Shift_JIS)"; use open OUT => ":encoding(Shift_JIS)"; my $infile = 'sjis2.txt'; my $outfile = 'sjis3.txt'; open(IN, "<$infile"); @lines = <IN>; close(IN); open(OU, ">$outfile"); print @lines; close(OU); 4)one.pl を実行し、続いてtwo.plを実行すると 以下のエラーがコマンドプロンプトに表示されます。 #------------------------------------------- D:\zipcode\utf8mondai>two.pl Wide character in print at D:\zipcode\utf8mondai\two.pl line 14. "・趣セゑスカ・イ・・セ橸スウ" Wide character in print at D:\zipcode\utf8mondai\two.pl line 14. "蛹玲オキ驕・ これは何故なのでしょうか。 エラーメッセージは、printしようとしている 文字列にutf8フラグがついているという意味 らしいです。

    • ベストアンサー
    • Perl
  • テキストを参照としたPerlによる名前の変更

    よろしくお願いします。ディレクトリ内のファイル名をテキストデータを参照として変更したいと思っております。まず、以下の参照テキストがあります。 sansyo.txt 1,2,1 2,3,1 3,4,2 4,5,3 6,7,9 ・ ・ ・ ・ このファイルを利用してディレクトリ内のファイルを以下のようにリネームします。 1,2.txt → 1,2,1.txt 2,3.txt → 2,3,1.txt 3,4.txt → 3,4,2.txt 4,5.txt → 4,5,3.txt 6,7.txt → 6,7,9.txt ・ ・ ・ ・ ・ ここで私は以下のプログラムを作成しました。 sansyo.pl ------------------------------ use strict; use warnings; my $dirname = '.'; opendir(DIR, $dirname) or die "$dirname: $!"; while (my $dir = readdir(DIR)) { next unless (-f $dir); next unless ($dir =~ /\.txt$/); print $dir, "\n"; open(FILE, $dir) or die "$dir: $!"; open(FILE2,"sansyo.txt"); my @file = <FILE>; my @file2 = <FILE2>; close(FILE); close(FILE2); foreach my $line2 (@file2) { my ($a,$b,$c) = split(/,/, $line2); if ($dir == $a.",".$b.".txt"){ rename ($dir, $a.",".$b.",".$c.".txt"); } } } closedir(DIR); 内容は、FILE2にsansyo.txtをforeachで1行ずつ読み込んでいき、 $a,$b.txtというファイルが$dirに読み込んだファイルにあったら、 $a,$b,$c.txtというファイルにリネームするという内容です。 ですが、いろいろ試行錯誤したもののうまくいきません。 具体的には、 Argument "1,2.txt" isn't numeric in numeric eq (==) at sansyo.pl line 23. とエラーがでて if ($dir == $a.",".$b.".txt"){ この部分でエラーが発生しているようです。 どなたか解決方法をよろしくお願いします。

    • ベストアンサー
    • Perl
  • 特定の数字を抜いて、行をずらしたいです。

    0 1 2 3 4      9 8 7 6 5 6 5 4 3 2 7 8 6 9 2 8 0 9 8 1   ↓ 0 1 2 6 4 9 8 7 3 5 6 5 4 9 2 7 8 6 8 2 8 0 9 最初の行のひとつの数字(左から4つ目:3)を抜いて、行をずらしたいのですが、つまづいています。 open (IN,"< $ARGV[0].csv") or die; open (OUT,"> $ARGV[0]_out.csv") or die; ####################################################### while($line =<IN>){ ($a, $b, $c, $d, $e) = split(/\s+/,$line); if($d == "3"){ $d == "" } print OUT (////////\n); } 分割してから、3を抜いてずらしたいのですがうまくいきません。 お助けいただきたく、どうぞよろしくお願い致します。

    • ベストアンサー
    • Perl
  • Perlでのファイル入出力、処理方法

    メモ帳で以下のようなプログラムを書きました。(file_1.plで保存しました) #!/usr/bin/perl $file="data.csv"; $cityfile="name.txt"; $outfile="data_out.csv"; open (IN, $file) or die "$!"; open (FILE, $file) or die "$!"; open (OUT, ">$outfile") or die "$!"; @city = <FILE>; ・ ・ ・ これをCygwinコマンド上で、 perl file_1.pl と入力し、Enterを押すと「No such file or directory at file_1.pl line 9.」と表示されます。 line9はopen (FILE, $file) or die "$!";という文です。 どこが間違えで、どのように修正すればよいのでしょうか。 よろしくお願いします。

  • ディレクトリ内のテキストファイルに対する同一処理

    よろしくお願いします。現在Linuxの環境でテキスト処理をしております。 ディレクトリ内にファイル名の異なった以下のような大量ファイルがあります。 a.txt 0,1,2,3,4,5,6,7 1,2,3,4,5,6,7,8 b.txt 2,3,4,5,6,7,8,9 3,4,5,6,7,8,9,10 これらのファイルをカンマでsplitし、左から2番目の数にだけ1を引き,下のディレクトリであるoutに出力させます。出力は以下のようになります。 ./out/a.txt 0,0,2,3,4,5,6,7 1,2,3,4,5,6,7,8 ./out/b.txt 2,2,4,5,6,7,8,9 3,4,5,6,7,8,9,10 そこで以下のようなPerlのプログラムを作成しました。 use strict; use warnings; my $dirname = '.'; opendir(DIR, $dirname) or die "$dirname: $!"; while (my $dir = readdir(DIR)) { next unless (-f $dir); next unless ($dir =~ /\.txt$/); print $dir, "\n"; open(FILE, $dir) or die "$dir: $!"; my @file = <FILE>; foreach $line (@file) { my ($a,$b,$c,$d,$e,$f,$g,$h) = split(/,/, $line);      my $b = $b - 1; close(FILE); } open(NEWFILE, "> ./out/$dir") or die "$dir: $!"; print NEWFILE @file; close(NEWFILE); } closedir(DIR); ですが、出力は完了するのですが、元のファイルから計算がされていません。どこがどう間違えているのかご指摘よろしくお願い申し上げます。

    • ベストアンサー
    • Perl
  • perl初心者です。宜しくお願い致します。

    ファイルの容量が大きく。perlを使用してデータの集計をしています。 "A"がきたらflag1をたてなさい。 "B"がきたらflag2をたてなさい。 "C"がきたらflag3をたてなさい。 これでAとBとCを抜き取ること&AからCまでの時間を取得したのですが、 Bの数のmaxの値だけを抜き取りたいのですが、Bがきたときの数をすべて 出力してしまいます。下記の文だと、Bが4回きたら、1,2,3,4と出力してしまいます。 それで4だけを出力したいのですがどのように書き換えたらようか教えて頂けますでしょうか。 '----------------------------------------------------------------------------- open (IN,"< $ARGV[0].txt") or die; open (OUT,"> $ARGV[0]_out.txt") or die; $flag =0; my $a, $b, $c; $count = 0; ####################################################### while($line =<IN>){ ($time,$data) = split(/\s+/,$line); if($data eq "A") { $flag=1; $a = $time; #print OUT $line; #print OUT "\n"; } elsif($data eq "B"){ $flag=2; $count++; $count == $data; print OUT ("$count\n") } #print OUT ("$count\n"); elsif($data eq "C"){ $flag=0; $count=0; $b = $time; $c = $b - $a; print OUT ("time $c\n") } } -------------------------------------------------------------------------------

  • 下のディレクトリ(3つ)に含まれる同じファイル名のテキストを結合し,カレントディレクトリに出力する

    いつもお世話になっております.環境はWindows XPのActiveperlです. やりたいことは「下のディレクトリ(3つ)に含まれる同じファイル名のテキストを結合し,カレントディレクトリに出力する」ことです.具体的にはいかのようにしたいと思っています. 現在のディレクトリ/a/1.txt a b c 現在のディレクトリ/b/1.txt d e f 現在のディレクトリ/c/1.txt g h i 現在のディレクトリ/1.txt a b c d e f g h i ここで私は以下のプログラムを作成しました. use strict; use warnings; my $dirname1 = './a/'; my $dirname2 = './b/'; my $dirname3 = './c/'; opendir(DIR1, $dirname1) or die "$dirname1: $!"; while (my $dir1 = readdir(DIR1)) { next unless (-f $dir1); next unless ($dir1 =~ /\.txt$/); opendir(DIR2, $dirname2) or die "$dirname2: $!"; while (my $dir2 = readdir(DIR2)) { next unless (-f $dir2); next unless ($dir2 =~ /\.txt$/); opendir(DIR3, $dirname3) or die "$dirname3: $!"; while (my $dir3 = readdir(DIR3)) { next unless (-f $dir3); next unless ($dir3 =~ /\.txt$/); if (($dir1 == $dir2) && ($dir2 == $dir3)){ open(FILE1, $dir1) or die "$dir1: $!"; my $line1 = <FILE1>; close(FILE1); open(FILE2, $dir2) or die "$dir2: $!"; my $line2 = <FILE2>; close(FILE2); open(FILE3, $dir3) or die "$dir3: $!"; my $line3 = <FILE3>; close(FILE3); my $joint_line = $line1.$line2.$line3; open(NEWFILE, "> $dir1") or die "$dir1: $!"; print NEWFILE $joint_line; close(NEWFILE); } } } } closedir(DIR1); closedir(DIR2); closedir(DIR3); ですが,以下のようなエラーが発生しています. closedir() attempted on invalid dirhandle DIR2 at joint.pl line 51. closedir() attempted on invalid dirhandle DIR3 at joint.pl line 52. ディレクトリハンドルが使われているけれど閉じているか実際にはディレクトリハンドルでは無い時にこれらの警告が発行されるとこの警告がでるようですが,どのようにしたら解決できるのでしょうか.よろしくお願いします.