从大文件中删除重复项

时间:2012-06-19 21:07:06

标签: unix sorting uniq

我有一个~20GB的csv文件。 样本文件:

1,a@a.com,M
2,b@b.com,M
1,c@c.com,F
3,d@d.com,F

此文件中的主键是第一列。 我需要写两个文件,uniq.csv和duplicates.csv

uniq.csv应包含所有非重复记录,duplicates.csv将包含所有具有当前时间戳的重复记录。

uniq.csv

1,a@a.com,M
2,b@b.com,M
3,d@d.com,F

duplicates.csv

2012-06-29 01:53:31 PM, 1,c@c.com,F

我正在使用Unix Sort,以便我可以利用其外部R-Way合并排序算法

To identify uniq records
tail -n+2 data.txt | sort -t, -k1 -un > uniq.csv

To identify duplicate records
awk 'x[$1]++' FS="," data.txt | awk '{print d,$1}' "d=$(date +'%F %r')," > duplicates.csv

我想知道是否有任何方法可以通过单个扫描这个大文件找到重复项和uniq?

3 个答案:

答案 0 :(得分:2)

你的awk脚本几乎就在那里。要查找唯一行,您只需使用in运算符来测试条目是否在关联数组中。这允许您一次性通过数据文件收集数据,并避免必须调用sort

tail -n +2 data.txt | \
awk '
    BEGIN { OFS=FS="," }
    {
        if (!($1 in x)) {
            print $0 > "/dev/fd/3"
        }
        x[$1]++
    }
    END {
        for (t in x) {
            print d, t, x[t]
        }
    }' d="$(date +'%F %r')" 3> uniq.csv > duplicates.csv

答案 1 :(得分:0)

我在几次工作前的一次采访中得到了这个问题。

一个答案是将uniq与“-c”(计数)选项一起使用。计数为“1”的条目是唯一的,否则不是唯一的。

  

排序foo | uniq -c | awk'{if($ 1 == 1){write-to-unique} else {write-to-duplicate}'

如果你想编写专用程序和/或避免排序造成的延迟,我会使用Python。

  

读取输入文件,对每个条目进行散列,并为您遇到的每个唯一键读取一个整数值。请记住,即使两个项不相等,哈希值也会发生冲突,因此请将每个键与其计数分开。   在输入的EOF上,遍历哈希结构并将每个条目吐入两个文件中的一个。

     

您似乎不需要排序输出,只需要分类输出,因此散列应该更快。构造哈希是O(1),而排序是O(我忘了;是unix排序Nlog(N)?)

答案 2 :(得分:0)

以下是perl上的代码,它将在一次扫描中进行处理

#!/usr/bin/perl
open(FI,"sort -t, -k1 < file.txt |");
open(FD,">duplicates.txt");
open(FU,">uniques.txt");
my @prev;
while(<FI>)
{
    my (@cur) = split(',');
    if($prev[0] && $prev[0]==$cur[0])
    {
        print FD localtime()." $_";
    }
    else
    {
        print FU $_;
    }
    @prev=@cur;
}