通过匹配键和筛选列来过滤具有重复项或重复项++的行

Filter rows with duplicates or triplicates++ by matching key and screening columns

我被重复/三次过滤的复杂性困住了。解决方案最好是 awk,但也可以是 sort -u 或 unique 等

我想过滤前三列中具有唯一或精确 duplicate/triplicate 等值的行。应该打印整行,包括不应匹配任何内容的第四列。考虑这个制表符分隔的 table:

编辑:不必在一行中比较 $2 和 $3 值。按照建议,我将 $3 值更改为 2xx。

name value1 value2 anyval
a 1 21 first
b 2 22 second
b 2 22 third
c 3 23 fourth
c 3 28 fifth
d 4 24 sixth
d 4 24 seventh
e 4 25 eighth
e 4 25 ninth
f 7 27 tenth
f 7 27 eleventh
f 7 27 twelveth
f 7 27 thirteenth
g 11 210 fourteenth
g 10 210 fifteenth

第 1 行是唯一的,应该打印出来。 第 2 + 3 行包含完全重复的值,应打印其中一个。 第 4 + 5 行在第 3 列中包含不同的值,应该被踢出。 第 6 + 7 行是重复的,但它们应该被踢掉,因为第 8 + 9 行在第 2 列中包含相同的值。 第 8 + 9 行相同。 应该打印第 10 到 13 行之一。

期望的输出:

a 1 21 first
b 2 22 second
f 7 27 tenth

...或 b 和 f 中的任何其他值。


到目前为止我得到但失败的:

awk '!seen[]++ && !seen[]'

打印所有基于列 1 的重复行

a   1   21  first
b   2   22  second
c   3   23  fourth
d   4   24  sixth
e   4   25  eighth
f   7   27  tenth

awk '!seen[]++ && !seen[]++'

打印

a   1   21  first
b   2   22  second
c   3   23  fourth
d   4   24  sixth
f   7   27  tenth

因此,如果出现以下情况,awk 应该打印出所需的结果:

awk '!seen[]++ && !seen[]++ && !seen[]++'

但是输出是空的。


另一种尝试:在第 1 列中打印重复项,然后对第 2 列和第 3 列再次执行相同的程序 - 不起作用,因为第 2 列中存在重复项

awk -F'\t' '{print }' file.txt |sort|uniq -d|grep -F -f - file.txt

首先打印 col 1 中的重复项,而没有 "a",稍后我可以 cat

b   2   22  second
b   2   22  third
c   3   23  fourth
c   3   22  fifth
d   4   24  sixth
d   4   24  seventh
e   4   25  eighth
e   4   25  nineth
f   7   27  tenth
f   7   27  eleventh
f   7   27  twelveth
f   7   27  thirteenth

但是,我再次遇到跨越多列的重复值(例如 4)。


我认为解决方案可能是定义 col1 单峰和多重峰并筛选所有其他列中的重复值,但这导致我的大脑出现大量堆栈溢出。

我不是 100% 清楚要求,但您可以分阶段筛选记录...

$ awk '!a[,,]++{print [=10=],}' file | 
  uniq -uf4 | 
  cut -d' ' -f1-4

a 1 1 first
b 2 2 second
f 7 7 tenth

first awk 根据前三个字段过滤所有重复条目并打印下一个进程使用的第二个字段,唯一过滤器仅基于第二个字段(现在在第四位置)并删除所有copies of duplicates, cut 去掉多余的关键字段。

更新

为了过滤唯一的 $2 和 $3 字段,我们必须恢复到 awk

$ awk '!a[,,]++ {f2[]++; f3[]++; line[,]=[=11=]} 
       END            {for(i in f2) 
                         for(j in f3) 
                           if((i,j) in line && f2[i]*f3[j]==1) print line[i,j]}' file | 
  sort

a 1 1 first
b 2 2 second
f 7 7 tenth