2

我有一个 ~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

重复.csv

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

我正在使用 Unix Sort,以便我可以利用它的 External 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 ?

4

3 回答 3

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
于 2012-07-01T13:41:48.667 回答
0

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

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

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

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

读取输入文件,对每个条目进行哈希处理,并为您遇到的每个唯一键 ++ 一个整数值。请记住,即使两个项目不相等,哈希值也可能发生冲突,因此请单独保留每个键及其计数。在输入的 EOF 处,遍历哈希结构并将每个条目吐到两个文件之一中。

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

于 2012-06-19T21:41:02.717 回答
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;
}
于 2012-06-19T22:06:14.537 回答