下記、perlスクリプトで通常は逆順に並べ替えることができると思うのですが、ファイルの行数が1000万行程度あり、実行すると、PCのメモリを食いつぶしてしまいまともに動作しません。
どのようにすればよいでしょうか?
もしくは、これに相当するようなフリーソフトはありますか?
ご存知の方教えてください。
宜しくお願い致します。
#!/usr/local/bin/perl
open(OUT, "1all.txt");
open (FH , ">out_all.txt");
print FH foreach( reverse <OUT> );
close(FH);
close(OUT);
No.4ベストアンサー
- 回答日時:
サンプルファイルとかがない上に、そんなに巨大ファイルを扱ったことがないので、上手くいくかどうか分かりませんが、試行錯誤を含めたサンプルプログラムを書いてみました。
@data=(1..100);
$name="file.txt";#完成ファイル名
$line=10;#一度に処理する行数
my($dir)=&makedir;#作業ディレクトリ作成
my($fn)=(0);
while(@data){
my(@save);
for($n=$line;$n>0;--$n){#$line行読み込んで、逆順に配列に入れる
unshift(@save,shift(@data));
}
++$fn;
&fsave($fn,@save);#ファイル一時保存
sleep 1;#1秒休憩。休憩できたら嬉しいな。
print "$fn完了\n";#待ってる間が怖いので、終了するたびにコメント。本当はいらない
}
&makefile($dir,$name);#ファイル結合
rmdir($dir);#一時ディレクトリ削除
sub makedir{#作業用ディレクトリ作成
my($fd)=(0);
while(-d "tmp$fd"){++$fd;}
mkdir("tmp$fd",0755);
return "tmp$fd";
}
sub fsave{#一時ファイルの作成
my($f)=shift(@_);
open(FILE,">$dir/$f")||die "Open Error";
print FILE @_;
close(FILE);
}
sub makefile{#ファイル結合
opendir(DIR,$_[0]);
my(@list)=readdir(DIR);
closedir(DIR);
shift(@list);#.削除。ここら辺かっこ悪いけど
shift(@list);#..削除。まぁ、動けばいいということで。
#ファイルの並び替え。数字大……小へ
my($i,$j);
for($i=$#list;$i>0;--$i){
for($j=0;$j<$i;++$j){
if($list[$j]<$list[$j+1]){
my($wk)=$list[$j];
$list[$j]=$list[$j+1];
$list[$j+1]=$wk;
}else{}
}
}
my($name)=$_[1];
while(@list){
my($file)=shift(@list);
#データ読み込み
open(FILE,"<$dir/$file")||die "Open Error";
my(@tmp)=<FILE>;
close(FILE);
#データ追加書き込み
open(FILE,">>$name")||die "Open Error";
print FILE @tmp;
close(FILE);
unlink("$dir/$file");
}
}
kumozさんの小分けにファイルに分けて、後で結合方式を使ってみたサンプルプログラムです。数を多くしたら待つ時間が嫌になったので、設定された数は少なめですが、そこら辺はいじって試して見てください。
処理が多くなるので、sleepで一定処理ごとに休ませてみたのですが、本当に休めるのかどうか分かりません。ただ、$lineの数だけファイルにまとめたら、一秒動作を止めてみました。意味がないならsleep関数はいりませんね。
工夫したところは、一時フォルダに一時ファイルをまとめて入れて、後で削除するようにしたところ。それとファイルの開き方を追加書き込みにして、どんどんとデータを追加していく方法を取ったことくらいでしょうか。できる限り、メモリに大量のデータを溜め込まないようにしてみた……つもりです。
なるべく流れをすっきりさせることを意識したので、脂肪がたくさんついている上に、何となく幼いプログラムになってしまいましたが、役に立てば嬉しいです。
皆様へ
たくさんの回答いただきありがとうございます。
perl初心者でしっかり、コードを研究して実行しようと思います。
回答いただき、本当に、ありがとうございました!!
No.3
- 回答日時:
ディスクスペースに余裕があれば、分割して処理する方法があると思います。
以下のプログラムは、10 万行ずつ逆順に並べ替えたものをファイルに保存し
ておいて、後から結合しています。
use strict;
open IN, "all.txt" or die "Can't open all.txt: $!";
my @line_100000; my $file_no = 0;
while (my $line = <IN>) {
unshift @line_100000, $line;
if (@line_100000 == 100000 or eof(IN)) {
$file_no++;
my $part = "part$file_no";
open OUT, ">$part" or die "Can't open $part: $!";
print OUT @line_100000;
close OUT or die "Can't close $part: $!";
@line_100000 = ();
}
}
close IN or die "Can't close all.txt: $!";
open OUT, ">out_all.txt" or die "Can't open out_all.txt: $!";
foreach my $i (reverse(1 .. $file_no)) {
my $part = "part$i";
open IN, "$part" or die "Can't open $part: $!";
print OUT <IN>;
close IN or die "Can't close $part: $!";
unlink $part or die "Can't delete $part: $!";
}
close OUT or die "Can't close out_all.txt: $!";
No.2
- 回答日時:
こんにちは、
標準モジュールじゃなくても良いなら、
File::ReadBackwards というモジュールがあるみたいですよ。
本で見て、試しに使ってみた程度ですけど、
ダウンロードしたモジュールを適当なディレクトリに置いて
use lib qw(適当なディレクトリ);
したら使えました。
参考URL:http://search.cpan.org/~uri/File-ReadBackwards-1 …
No.1
- 回答日時:
use Tie::File;
my @lines;
tie @lines, 'Tie::File', '1all.txt' or die $!;
して、@linesを逆から読むとか。
for (my $i=@lines; $i>0; $i--) {
print $lines[$i];
}
詳しい使い方は perldoc Tie::File で。
Perlのバージョンが5.8.0以降ならTie::Fileは標準で
ついているはず。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
関連するカテゴリからQ&Aを探す
おすすめ情報
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
パスワードを外部ファイルから...
-
die関数のエラー出力先について
-
バッチファイルの作り方(CSV→...
-
openした後、closeしないでプロ...
-
ExcelをCSV書き出す場合のシー...
-
VBAコードを張り付け後のエクセ...
-
VBAでCSVファイルを途中行まで...
-
エクセルVBA コードが同じでも...
-
データの日付でソートをしたい
-
awkスクリプトでダブルクォーテ...
-
VBAで巨大なファイルの途中から...
-
dos変数の%~dp0は powershellで...
-
VBAでCSVファイルの特定行を書...
-
Perl エラーログを指定の場所...
-
PerlからのCSV出力
-
MATLAB グローバル変数の宣言
-
時刻表を分でソートする方法を...
-
ReadLineでの読み出し行を指定する
-
エクセルVBAで素数だけを出力す...
-
sprintfについて
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
close()で例外が投げられる理由
-
改行コードが勝手に
-
perlで大容量CSVのsort方法につ...
-
die関数のエラー出力先について
-
open中のファイルをrename
-
perlを用いた特定文字列間の抽...
-
AutoCADのスクリプト
-
microsoft multimedia control ...
-
perlでURLから画像ファイルを作...
-
perlでファイル内の文字列を置...
-
巨大ファイルの行をを逆順に並...
-
オープンしたファイルで行の連結
-
ハッシュにファイルハンドル
-
Perl:ファイルハンドルをスカラ...
-
perlで、文字列の中から何番目...
-
Perlでファイル出力時にデッド...
-
プログラムのヒントを下さい
-
ファイルから読み込んだ文字を
-
パスワード自動生成スクリプト...
-
Perl変数から外部プログラムの...
おすすめ情報