删除重复行而不排序[重复]

问题描述 投票:0回答:8

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

这个简单的功能(

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

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

shell scripting filter uniq
8个回答
388
投票

UNIX Bash 脚本博客建议

awk '!x[$0]++'

该命令告诉 awk 要打印哪些行。变量

$0
保存一行的全部内容,方括号是数组访问。因此,对于文件的每一行,数组
x
的节点都会递增,如果该节点的内容先前未设置 (
!
),则打印该行。


102
投票

一个迟来的答案 - 我刚刚遇到了这个的重复 - 但也许值得添加......

@1_CR的答案背后的原理可以写得更简洁,使用

cat -n
代替
awk
来添加行号:

cat -n file_name | sort -uk2 | sort -n | cut -f2-
  • 使用
    cat -n
    添加行号
  • 使用
    sort -u
    删除重复数据(
    -k2
    表示“从字段 2 开始作为排序键”)
  • 使用
    sort -n
    按前缀数字排序
  • 使用
    cut
    删除行编号(
    -f2-
    表示“选择字段 2 直到结束”)

10
投票

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

awk '!a[$0]++' file1.csv file2.csv

6
投票

uq

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

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

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

5
投票

Michael Hoffman 的上述解决方案简短而有趣。对于较大的文件,Schwartzian 变换方法涉及使用 awk 添加索引字段,然后进行多轮排序和 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'

2
投票

谢谢1_CR!我需要一个“uniq -u”(完全删除重复项)而不是 uniq(保留 1 个重复项副本)。 awk 和 perl 解决方案无法真正修改来执行此操作,但您可以!我可能还需要较低的内存使用,因为我将像 100,000,000 行 8-) 那样进行统一。为了以防万一其他人需要它,我只需在命令的 uniq 部分添加一个“-u”:

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

-1
投票

我只是想删除以下行中的所有重复项,而不是文件中的所有重复项。所以我用了:

awk '{
  if ($0 != PREVLINE) print $0;
  PREVLINE=$0;
}'

-3
投票

uniq
命令甚至可以在别名中工作http://man7.org/linux/man-pages/man1/uniq.1.html

© www.soinside.com 2019 - 2024. All rights reserved.