Unix 从大文件中删除重复项
我有一个~20GB的csv文件。 示例文件: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,
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
构建散列会占用内存太多,不是吗?