通过匹配键和筛选列筛选具有重复或三次重复的行

时间:2017-01-05 13:46:34

标签: awk filter duplicates screen

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

我想在前三列中过滤具有唯一或完全重复/重复等值的行。应打印包括第四列不应匹配任何内容的整行。请考虑这个以制表符分隔的表:

编辑:不必在一行内比较$ 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[$1]++ && !seen[$2]'

根据col 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[$1]++ && !seen[$2]++'

打印

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

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

awk '!seen[$1]++ && !seen[$2]++ && !seen[$3]++'

但输出是空的。

另一种尝试:在第1列中打印重复,然后再次在第2列和第3列中执行相同的过程 - 因为第2列中有dulicates

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

首先打印col 1中没有“a”的重复项,我可以稍后再说

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 singlets和multiplets以及屏幕显示所有其他列中的重复值,但这会导致我脑中出现大量堆栈溢出。

1 个答案:

答案 0 :(得分:1)

我不是100%明白要求,但您可以分阶段过滤记录......

$ awk '!a[$1,$2,$3]++{print $0,$2}' file | 
  uniq -uf4 | 
  cut -d' ' -f1-4

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

首先awk根据前三个字段过滤所有重复条目,并打印下一个过程要使用的第二个字段,仅基于第二个字段(现在位于第四个位置)的唯一过滤器并删除所有副本重复,切除了额外的关键字段。

<强>更新

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

$ awk '!a[$1,$2,$3]++ {f2[$2]++; f3[$3]++; line[$2,$3]=$0} 
       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