确定文本文件中唯一性和重复性的最佳方法

时间:2009-03-13 20:55:07

标签: unix command-line shell

我有一个大约2000万行的文本文件。每行长度为25个字符。我估计大概有大约200k-300k的独特线路。我想知道的是究竟有多少条独特的线条,以及每条线条出现的次数(我希望结果是幂律式的)。

我可以这样做:

sort bigfile|uniq -c |sort -nr > uniqcounts
wc -l uniqcounts

但这是非常低效的记忆和时间。

这个问题的最佳命令行解决方案是什么?

5 个答案:

答案 0 :(得分:6)

当我遇到像这样的文本处理问题时,我倾向于倾向于Perl,特别是因为Perl安装在大多数Unix系统上。 (你可以用awk做同样的事情,这可能会更有用。)

这样的事情可以解决问题:

#!/usr/bin/perl

while(<>) {
    chomp;
    $lines{$_}++;
}

print "Total unique lines: ", scalar(keys %lines), "\n";
foreach my $line (sort {$lines{$b} <=> $lines{$a}} keys %lines) {
    printf "%6d  %s\n", $lines{$line}, $line;
}

(你可以将其作为一个单行,但是分解使其更容易阅读。)

这需要O(n)内存用于散列键,其中 n 是唯一行的数量。运行时效率取决于散列查找,但介于O(n)(如果没有散列冲突)和O(n * log n)(对于平衡树)之间。在最坏的情况下,最终的可选排序可能需要O(n ^ 2),如果唯一行的数量很高,则可能在运行时占主导地位。

答案 1 :(得分:2)

我承担了被认为是偏离主题和被投票的风险,但我必须对此抱怨。

20百万* 25个字符= 500000000字节(假设您不是指Unicode)

这不到500 MB的RAM。对于现代计算机而言,这不是一个巨大的数字。

请不要抱怨这是非常低效的记忆和时间。将冗余数据存储在平面文本文件中的决定是低效且错误的。

使用数据库(例如sqlite)而不是平面文件。

使用类似

的表格
CREATE TABLE lines (line VARCHAR(25), occurences INTEGER)

存储独特的线条及其出现。

如果不是您的应用程序生成此文本文件,请向开发人员抱怨它!

答案 2 :(得分:1)

确保在测试sortuniq解决方案之前执行此操作:

export LC_ALL=C

如果你至少可以比较这个和perl解决方案的时间,那将是件好事。

答案 3 :(得分:1)

使用 awk (在 Solaris上使用 nawk / usr / xpg4 / bin / awk

awk 'END {
  for (k in _)
    print k, _[k]
    }
{ _[$0]++ }
' infile

答案 4 :(得分:0)

我不确定是否有比您发布的解决方案更好的解决方案:O(n log(n)+ n)。鉴于问题陈述,你提到的精细的“sort -nr”并不是绝对必要的,但是使得输出更容易为人类所知。

如果有人能提出比这更快的解决方案(复杂性),我会非常感兴趣。当然,编写一个专用程序来做同样的事情可能比使用sort和uniq更快。