命令行的替代方法"sort | uniq -c | sort -n"

oli*_*bre 2 sorting shell perl awk count

我使用sort | uniq -c | sort -n多年但今天它失败了,因为我的输入文件是10 GB而我的/tmp宽度为1 GB:

sort: write failed: /tmp/sortmIGbL: No space left on device

因此,我正在寻找日常使用的有效替代方案:

  • awk 可以使用但没有排序的关联数组

  • perl似乎是一个不错的选择,但是来自perlmonks.org10年解决方案似乎不起作用

    no warnings;
    $^W=0;
    open my $in, $ARGV[0] or die "Couldn't open $ARGV[0]:$!";
    my ($buffer, %h) = ''; keys %h = 1024*500;
    while (sysread($in, $buffer, 16384, length $buffer)) {
        $h{$1}++ while $buffer =~ m[^(?:.+?\|){9}([^|]+)\|]mg;
        $buffer = substr($buffer, rindex($buffer, "\n"));
    }
    print scalar keys %h;
    
    Run Code Online (Sandbox Code Playgroud)

如何获得与sort | uniq -c | sort -nr | head非常大的文件相同的结果?

  • 因为我使用Linux/Cygwin/Solaris/*BSD/...我对任何想法都持开放态度(便携式或非便携式)
  • 您可以自由使用您想要的脚本语言(awk/ perl/ ...)

输入示例

a
BB
ccccc
dddddddd
a
BB
a
Run Code Online (Sandbox Code Playgroud)

其中一个可能的输出

    3 a
    2 BB
    1 dddddddd
    1 ccccc
Run Code Online (Sandbox Code Playgroud)

Thi*_*Not 5

首先sort在你的命令链是利用所有的资源之一.减少获得独特的线条和问题集中的第一,然后排序:

perl -ne '
    $count{$_}++;
    END {
        print "$count{$_} $_" for sort {
            $count{$b} <=> $count{$a} || $b cmp $a
        } keys %count
    }
' input.txt
Run Code Online (Sandbox Code Playgroud)

你有66,000个7字节的唯一行,因此对于每个标量,每个标量占用的内存为66,000*56个字节= 3,696,000个字节.这不包括散列的计数和开销,但毫无疑问,这种方法很容易实现.

  • @olibre,150万*7字节是10MB,而不是10GB!你的意思是15亿行? (2认同)