【问题标题】:Remove duplicates from a large file从大文件中删除重复项
【发布时间】:2012-06-19 21:07:05
【问题描述】:

我有一个 ~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 排序,以便我可以利用其外部 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?

【问题讨论】:

    标签: unix sorting uniq


    【解决方案1】:

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

    【讨论】:

      【解决方案2】:

      我在几份工作前的一次面试中得到了这个问题。

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

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

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

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

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

      【讨论】:

      • 构建哈希会占用大量内存,不是吗?
      【解决方案3】:

      这是 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;
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-01-24
        • 1970-01-01
        • 2013-03-27
        • 2020-01-01
        • 2019-09-20
        • 1970-01-01
        相关资源
        最近更新 更多