删除重复行而不进行排序

Rob*_*ino 92 shell scripting filter uniq

我在Python中有一个实用程序脚本:

#!/usr/bin/env python
import sys
unique_lines = []
duplicate_lines = []
for line in sys.stdin:
  if line in unique_lines:
    duplicate_lines.append(line)
  else:
    unique_lines.append(line)
    sys.stdout.write(line)
# optionally do something with duplicate_lines
Run Code Online (Sandbox Code Playgroud)

这个简单的功能(uniq无需先排序,稳定排序)必须作为简单的UNIX实用程序提供,不是吗?也许是管道中过滤器的组合?

询问的原因:在我无法从任何地方执行python的系统上需要此功能

Mic*_*man 243

UNIX Bash Scripting博客建议:

awk '!x[$0]++'
Run Code Online (Sandbox Code Playgroud)

这个命令告诉awk要打印哪些行.变量$0保存一行的全部内容,方括号是数组访问.因此,对于文件的每一行,x如果该节点的内容!先前未设置(),则会增加该数组的节点并打印该行.

  • 当然,将这个数组命名为例如`seen`而不是`x`会更加模糊不清,以避免给新手留下awk语法是线噪声的印象 (13认同)
  • 对于像这样的简短`awk`语句(不涉及大括号),该命令只是告诉awk要打印哪些行.变量`$ 0`包含一行的全部内容,方括号是数组访问.因此,对于文件的每一行,我们正在递增名为`x`的数组的节点,如果该节点的内容不是先前设置的(`!`),则打印该行. (6认同)
  • 我翻过的最紧凑,最精美的剧本.奖励! (5认同)
  • /sf/answers/101111391/ 详细描述了它的工作原理。 (3认同)
  • 也许这个命令会更容易理解 `awk '!($0 in x){x[$0]++; 打印 $0}` (2认同)
  • 请记住,这会将整个文件加载到内存中,因此不要在没有大量可用RAM的3GB文本文件上尝试此操作。 (2认同)
  • @Hitechcomputergeek这不一定会将整个文件加载到内存中,而只是将唯一的行加载到内存中。当然,如果所有行都是唯一的,则最终可能是整个文件。 (2认同)
  • 我不得不使用`awk'!mem [$ 0] ++ {print $ 0; fflush()}'`,因为否则缓冲会破坏我正在开发的脚本的意义。 (2认同)

Dig*_*uma 56

一个迟到的答案 - 我刚刚碰到了这个的副本 - 但也许值得补充......

@ 1_CR答案背后的原则可以更简洁地编写,cat -n而不是awk添加行号:

cat -n file_name | sort -uk2 | sort -nk1 | cut -f2-
Run Code Online (Sandbox Code Playgroud)
  • 使用cat -n前面加上行号
  • 使用sort -u删除重复数据
  • 用于sort -n按前缀编号排序
  • 使用cut去除行号

  • 易于理解,这通常很有价值。对于上面最短的Michael Hoffman解决方案,大文件的性能有何想法? (2认同)
  • 更具可读性/可维护性。需要相同但使用反向排序以仅保留每个唯一值的最后一次出现。在同一个排序命令中同时使用 `--reverse` 和 `--unique` 不会返回预期的结果。显然, sort 通过第一次在输入上应用“--unique”(以减少后续步骤中的处理)来进行过早的优化。这会过早地删除 `--reverse` 步骤所需的数据。要解决此问题,请在管道中插入 `sort --reverse -k2` 作为第一个排序:`cat -n file_name | 排序 -rk2 | 排序 -uk2 | 排序 -nk1 | 切-f2-` (2认同)
  • 只需 60 秒即可处理一个 900MB 以上的文本文件,其中包含大量(随机放置的)重复行,结果只有 39KB。足够快。 (2认同)
  • “管道”版本用于保留最后一次出现而不是第一次出现:`cat file_name | 猫 -n | 排序-rk2 | 排序-uk2 | 排序-nk1 | 切-f2-`。 (2认同)

Sho*_* Ya 6

uq

uq是一个用 Rust 编写的小工具。它执行唯一性过滤而无需先对输入进行排序,因此可以应用于连续流。

与投票最高的 awk 解决方案和其他基于 shell 的解决方案相比,该工具有两个优点:

  1. uq使用哈希值记住行的出现,因此当行很长时,它不会使用太多内存。
  2. uq可以通过设置要存储的条目数量限制来保持内存使用恒定(当达到限制时,有一个标志来控制是覆盖还是死亡),而当条目awk太多时,该解决方案可能会遇到 OOM线。


iru*_*var 5

迈克尔霍夫曼的解决方案是短暂而甜蜜的.对于较大的文件,Schwartzian变换方法涉及使用awk后跟多轮sort和uniq添加索引字段涉及较少的内存开销.以下代码段在bash中有效

awk '{print(NR"\t"$0)}' file_name | sort -t$'\t' -k2,2 | uniq --skip-fields 1 | sort -k1,1 -t$'\t' | cut -f2 -d$'\t'
Run Code Online (Sandbox Code Playgroud)


Azi*_*zSM 5

要从2个文件中删除重复项:

awk '!a[$0]++' file1.csv file2.csv
Run Code Online (Sandbox Code Playgroud)