删除重复的行,仅考虑两列

删除重复的行,仅考虑两列

如果我只考虑前两列,那么我有一个文件包含一些重复的行。

例如

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

在此示例中,我有一些行在前两列中有 1 1 或 4 4,对我来说,这些是重复的。最后,我希望得到如下结果:

2 2 7 7
1 1 3 3
3 3 7 7
4 4 9 9

我只想保留具有重复值 1 1 或 4 4 的行之一

使用类似这样的方法,我能够识别哪些是重复的行

 cut -f 1,2  file.txt | sort | uniq -D

但我仍然不确定如何删除所有重复的行而只留下一行,特别是因为其他两列不同。你能告诉我如何实现吗?

答案1

调整后awk的代码来自另一个答案

<file.txt awk '!seen[$1,$2]++'

它之所以有效,是因为awk 1打印每一行并且awk 0不打印任何行。我们使用一个计数出现次数的数组,只考虑前两个字段。后缀++会增加计数,但表达式中使用的是旧值(就像在 C 中一样)。!将任何非零值(意味着相同的两个字段已经出现过)转换为,0并将零值(……尚未出现过)转换为1

注意,中的多维数组awk实际上是一维数组。seen[$1,$2]相当于seen[$1 SUBSEP $2],并且的默认值SUBSEP是实现定义的(参见POSIX 规范)。GNU awk( gawk) 使用非常安全的字符\034(即034ASCII 中的八进制文件分隔符)。它是不可打印的字符,不太可能出现在awk程序或大多数输入数据中。

SUBSEP如果您怀疑所使用的 的默认值在和awk之间插入时可能会产生歧义字符串,那么您应该自行设置为一个安全的值。$1$2SUBSEP

通常,如果输入数据的字段严格由特定字符分隔,则您可能希望将此字符用作SUBSEP。例如,如果字段分隔符是制表符,则制表符不能出现在$1nor中$2。因此,是和(我们的两个索引)作为单个字符串$1"\t"$2的明确表示。示例代码:$1$2

​<file.txt awk 'BEGIN {FS="\t"; SUBSEP="\t"} !seen[$1,$2]++'

答案2

使用 GNU 排序:

sort -t ' ' -k 1,2 -u file

输出:

1 1 3 3
2 2 7 7
3 3 7 7
4 4 9 9

看:man sort

相关内容