从非常大的文本文件中删除重复的对

时间:2012-10-18 21:07:28

标签: bash perl awk

我有一个非常大的文本文件(几GB),格式如下:

1 2
3 4
3 5
3 6
3 7
3 8
3 9

文件已经排序,双线被删除。有一些重复的对象,比如我要删除的'2 1','4 3'相反的顺序。有没有人有任何解决方案在资源有限的环境中,BASH,AWK,perl或任何类似的语言?我无法加载整个文件并在值之间循环。

7 个答案:

答案 0 :(得分:4)

您想要删除第二个数字小于第一个数字的行吗?

perl -i~ -lane'print if $F[0] < $F[1]' file

答案 1 :(得分:3)

可能的解决方案:

  • 扫描文件
  • 对于第二个值小于第一个值的任何一对,交换两个数字
  • 再次按第一个数字
  • 排序对
  • 删除重复项

我仍在考虑在磁盘扫描方面提供更有效的解决方案,但这是一种基本的天真方法

答案 2 :(得分:2)

对于每个值,对硬盘驱动器上的文件执行二进制搜索,而不将其加载到内存中。如果看到,请删除副本。然后执行最后一次传递,删除两个或更多\n的所有实例。

答案 3 :(得分:2)

不确定这是否有效/是否有任何好处......

awk '{ if ($2 > $1) print; else print $2, $1 }' hugetext | sort -nu -O hugetext

答案 4 :(得分:1)

您想要删除重复项,并考虑1 22 1是否相同?

< file.in \
| perl -lane'print "@F[ $F[0] < $F[1] ? (0,1,0,1) : (1,0,0,1) ]"' \
| sort -n \
| perl -lane'$t="@F[0,1]"; print "@F[2,3]" if $t ne $p; $p=$t;' \
> file.out

这可以处理任意大的文件。

答案 5 :(得分:0)

perl -lane '
    END{
        print for sort {$a<=>$b} keys %h;
    }

    $key = $F[0] < $F[1] ? "$F[0] $F[1]" : "$F[1] $F[0]";
    $h{$key} = "";
' file.txt

说明

  1. 我按数字顺序对当前行进行排序
  2. 我通过将第一个和第二个值与空格连接来制作哈希键变量$key
  3. 我将$hash{$key}定义为
  4. 最后,我打印按数字顺序排列的所有键。
  5. 哈希键本质上是uniq,因此不重复。

    您只需使用Unix重定向来创建新文件。

答案 6 :(得分:0)

这是一般的O(n)算法,可以在1遍中完成此操作(无需循环或排序):

  1. 以空的哈希集作为黑名单开始(一个集合是一个只有键的地图)
  2. 一次读取一行文件。
  3. 每行:
    • 检查此对已经在您的黑名单中。
    • 如果是,请忽略它。
    • 如果没有,请将其附加到结果文件中;并将交换的值添加到黑名单中(例如,如果您只读“3 4”,并将“4 3”添加到黑名单)
  4. 这需要O(n)时间运行,并且O(n)存储为黑名单。 (如果您将文件作为r / w操作来删除行,而不是在黑名单中检查它们,则不会产生额外的存储空间)