如果我只考虑前两列,那么我有一个文件包含一些重复的行。
例如
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
(即034
ASCII 中的八进制文件分隔符)。它是不可打印的字符,不太可能出现在awk
程序或大多数输入数据中。
SUBSEP
如果您怀疑所使用的 的默认值在和awk
之间插入时可能会产生歧义字符串,那么您应该自行设置为一个安全的值。$1
$2
SUBSEP
通常,如果输入数据的字段严格由特定字符分隔,则您可能希望将此字符用作SUBSEP
。例如,如果字段分隔符是制表符,则制表符不能出现在$1
nor中$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