如何在perl中将文件加载到内存中

How loading of file into memory in perl

我已经尝试使用一些脚本按降序对输入文本文件进行排序并仅打印使用率最高的客户。

输入文本文件包含:

  NAME,USAGE,IP
  example :
  Abc,556,10.2.3.5
  bbc,126,14.2.5.6

等等,这是一个非常大的文件,我试图避免将文件加载到内存中。

我试过以下脚本。

use warnings ;

use strict;

my %hash = ();
my $file = $ARGV[0] ;


open (my $fh, "<", $file) or die "Can't open the file $file: ";

while (my $line =<$fh>) 
{
chomp ($line) ;
my( $name,$key,$ip) = split /,/, $line;

$hash{$key} = [ $name, $ip ];
}

my $count= 0 ;

foreach ( sort { $b <=> $a } keys %hash ){
my $value = $hash{$_};
print "$_  @{$value} \n" ;
last if (++$count == 5);
} 

输出应根据用途排序,它将显示各自用途的名称和 IP。 “`

我想你想打印文件中第二列中具有最高值的五行

这可以通过一种插入排序来完成,该排序检查文件的每一行,看它是否高于最近找到的五行中的最低行,但只累积文件的一个合理子集会更容易数据,对其进行排序,并丢弃除前五名以外的所有数据

在这里,我有一个数组 @top,其中包含文件中的行。当数组中有 100 行时,它被排序并减少到五个最大条目。然后 while 循环继续向文件中添加行,直到再次达到限制或已达到文件末尾,重复该过程。这样,文件中不超过 100 行对内存有帮助

我已经生成了一个 1,000 行的数据文件来测试它,在第 2 列中使用 100 到 2,000 之间的随机值。下面的输出是结果

use strict;
use warnings 'all';

open my $fh, '<', 'usage.txt' or die $!;

my @top;

while ( <$fh> ) {

    push @top, $_;

    if ( @top >= 100 or eof ) {

        @top = sort {
            my ($aa, $bb) = map { (split /,/)[1] } ($a, $b);
            $bb <=> $aa;
        } @top;

        @top = @top[0..4];
    }
}

print @top;

输出

qcmmt,2000,10.2.3.5
ciumt,1999,10.2.3.5
eweae,1998,10.2.3.5
gvhwv,1998,10.2.3.5
wonmd,1993,10.2.3.5

执行此操作的标准方法是创建一个包含 k 个项目的优先级队列,其中 k 是您要 return 的项目数。因此,如果您想要具有最高值的五行,您将执行以下操作:

pq = new priority_queue
add the first five items in the file to the priority queue
for each remaining line in the file
    if value > lowest value on pq
        remove lowest value on the pq
        add new value to pq

当您浏览完文件后,pq 将包含具有最高值的五个项目。

要在 Perl 中执行此操作,请使用 Heap::Priority 模块。

与其他建议相比,这会更快并且占用更少的内存。

算法记住最后 5 个最大的行。

对于每一行,检查记忆的最低元素。如果 more - 存储在下一个最大项目之前的数组中,unshift 最低。[​​=12=]

use warnings;
use strict;

my $file = $ARGV[0] ;
my @keys=(0,0,0,0,0);
my @res;

open (my $fh, "<", $file) or die "Can't open the file $file: ";
while(<$fh>)
{
 my($name,$key,$ip) = split /,/;
 next if($key<$keys[0]);
 for(0..4) {
  if($_==4 || $key<$keys[$_+1]) {
   @keys[0..$_-1]=@keys[1..$_] if($_>0);
   $keys[$_]=$key;
   $res[$_]=[ $name, $ip ];
   last;
  } 
 }
}
for(0..4) {
  print "$keys[4-$_]  @{$res[4-$_]}";
}

对来自 1M 随机行(20 MB)的文件进行测试:

Last items (This algorithm):
Start 1472567980.91183
End   1472567981.94729 (duration 1.03546 seconds)

full sort in memory (Algorithm of @Rishi):
Start 1472568441.00438
End   1472568443.43829 (duration 2.43391 seconds)

sort by parts of 100 rows (Algorithm of @Borodin):
Start 1472568185.21896
End   1472568195.59322 (duration 10.37426 seconds)