Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/sorting/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Unix 从大文件中删除重复项_Unix_Sorting_Uniq - Fatal编程技术网

Unix 从大文件中删除重复项

Unix 从大文件中删除重复项,unix,sorting,uniq,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 2012-06-29 01:53:31 PM, 1,c@c.com,F uniq.csv应包含所有非重复记录,而duplicates.csv将包含具有当前时间戳的所有重复记录 uniq.csv 1,a@a.com,M 2,b@b.com,M 3,d@d.com,

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

2012-06-29 01:53:31 PM, 1,c@c.com,F
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排序,以便能够利用其外部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?

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

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

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

如果您想编写一个专用程序和/或避免排序造成的延迟,我将使用Python

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

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


下面是一段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;
}
!/usr/bin/perl
打开(FI,“sort-t,-k1duplicates.txt”);
开放式(FU,“>uniques.txt”);
我的@prev;
while()
{
my(@cur)=拆分(',');
如果($prev[0]&&$prev[0]==$cur[0])
{
打印FD localtime();
}
其他的
{
打印FU$;
}
@prev=@cur;
}

您的
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

构建散列会占用内存太多,不是吗?