これは大まかな部分的な解決策です:
#!/usr/bin/perl
use strict;
use warnings;
my @lines = ();
while (<>) {
push @lines, $_;
@lines = sort @lines;
if (scalar @lines > 10) {
pop @lines;
}
}
print @lines;
入力データを 1 回だけ読み取り、上位 10 行の並べ替えられた配列を継続的に維持します。
もちろん、毎回配列全体をソートするのは非効率的ですが、ギガバイトの入力の場合でも、 よりも大幅に高速になると思いますsort huge-file | head
。
印刷される行数を変更するオプションを追加するのは簡単です。並べ替えの方法を制御するオプションを追加するのは少し難しくなりますが、CPANにそれを助ける何かがあっても驚かないでしょう。
より抽象的に言えば、大きな配列から最初の N 個の並べ替えられた要素だけを取得する 1 つの方法は、部分的なクイック並べ替えを使用することです。この場合、必要でない限り、正しいパーティションを並べ替える必要はありません。これには、配列全体をメモリに保持する必要がありますが、これはおそらくあなたのケースでは実用的ではありません。
入力を中サイズのチャンクに分割し、巧妙なアルゴリズムを適用して各チャンクの上位 N 行を取得し、チャンクを連結してから、同じアルゴリズムを結果に適用できます。チャンクのサイズによっては、sort ... | head
十分に賢いかもしれません。これを行うために使用するシェル スクリプトをまとめるのは難しくありませんsplit -l ...
。
(必要に応じて手を振ってください。)
免責事項:私はあなたが作業しているものよりもはるかに小さいファイル(約170万行)でこれを試しましたが、私の方法はsort ... | head
.