7

行が次の形式になっているテキスト ファイルを並べ替えようとしています。

! ! ! ! ! ||| ! ||| 1.25846e-05 0.248369 3.02708e-07 0.662955 2.718 ||| 0-0 1-0 2-0 3-0 4-0 ||| 476773 1.98211e+07 6

最後の数字 (つまり、この例では 6) で数値的に降順に並べ替えたいとします。行には、スペースを区切り文字として使用する予測可能な列数がありませんが、||| を使用しています。区切り文字として常に 5 つの列があり、最後の列には常にスペースで区切られた 3 つの数字があり、その最後の数字が並べ替えの基準になります。テキスト ファイルは約 15 GB で、それを行うために書いた perl スクリプトがありましたが、perl がファイル全体を一度にロードするため、32 GB の RAM を搭載した古いラップトップでしか機能しませんでした。今、私は 8 GB の RAM で立ち往生しており、スワップ ファイルを何日もかき回すだけです。標準の Linux の sort コマンドの方が巨大なファイルをより適切に処理できると聞いたことがありますが、最後の番号を使用する方法が見つかりません。

4

4 に答える 4

0

問題は RAM なので、おそらく を使用して必要なメモリを減らすことができますTie::File。配列内のインデックスで行を参照できるようになります。ソートする数値を取得し、Schwartzian 変換を使用してソートされたインデックスのリストを取得し、最後にファイルを再印刷するだけです。

use strict;
use warnings;
use Tie::File;

my $file = shift;                           # your filename argument
tie my @lines, 'Tie::File', $file or die $!;
my @list = map $_->[0],                     # restore line number
           sort { $b->[1] <=> $a->[1] }     # sort on captured number
           map { [ $_, $lines[$_] =~ /(\d+)$/ ] } 0 .. $#lines;
           # store an array ref [ ... ] containing line number and number to 
           # sort by
@lines = @lines[@list];

最後の操作は、ファイルをソートされた順序で保存します。これは永続的な変更であるため、バックアップを作成してください。また、おそらく高価な操作であり、Tie::Fileいくつかのパフォーマンスの問題がありました。それを行う別の方法は、おそらく安価ですが、数値のリストを単純に繰り返し処理し、行ごとに新しいファイルに出力することです。

open my $fh, ">", "output.csv" or die $!;
for my $num (@list) {
    print $fh $lines[$num], $/;
}

このファイルへの直接出力により、出力のリダイレクトに必要なシェル キャッシュが回避されます。

于 2013-09-20T13:35:06.130 に答える