awk完全根据特定列值删除重复行

时间:2016-10-03 04:45:11

标签: sorting awk uniq

我得到了一个数据集:

6   AA_A_56_30018678_E  0   30018678    P   A
6   SNP_A_30018678  0   30018678    A   G
6   SNP_A_30018679  0   30018679    T   G
6   SNP_A_30018682  0   30018682    T   G
6   SNP_A_30018695  0   30018695    G   C
6   AA_A_62_30018696_Q  0   30018696    P   A
6   AA_A_62_30018696_G  0   30018696    P   A
6   AA_A_62_30018696_R  0   30018696    P   A

如果col 4有重复项,我想删除所有行。

我使用下面的代码(使用sort,awk,uniq和join ...)来获取所需的输出,但有没有更好的方法呢?

sort -k4,4 example.txt | awk '{print $4}' | uniq -u  > snp_sort.txt

join -1 1 -2 4 snp_sort.txt example.txt | awk '{print $3,$5,$6,$1}' > uniq.txt

这是输出

SNP_A_30018679  T   G   30018679
SNP_A_30018682  T   G   30018682
SNP_A_30018695  G   C   30018695

6 个答案:

答案 0 :(得分:2)

使用awk过滤掉重复的行并打印那些恰好出现一次的行。

awk '{k=($2 FS $5 FS $6 FS $4)} {a[$4]++;b[$4]=k}END{for(x in a)if(a[x]==1)print b[x]}' input_file

SNP_A_30018682 T G 30018682
SNP_A_30018695 G C 30018695
SNP_A_30018679 T G 30018679

这个想法是: -

  1. 将所有唯一$4条目存储在一个数组(a)中,并为数组b
  2. 维护一个计数器
  3. 打印数组以查找恰好出现一次的条目。

答案 1 :(得分:2)

使用命令替换:首先在第四个字段中仅打印unique列,然后grep这些列。

grep "$(echo  "$(awk '{print $4}' inputfile.txt)" |sort |uniq -u)" inputfile.txt
6   SNP_A_30018679  0   30018679    T   G
6   SNP_A_30018682  0   30018682    T   G
6   SNP_A_30018695  0   30018695    G   C

注意:如果您要打印前四列,请在命令末尾添加awk '{NF=4}1'。当然,您可以通过更改$4NF=4的值来更改列数。

答案 2 :(得分:1)

由于您的“密钥”是固定宽度,因此uniq需要-w来检查它。

sort -k4,4 example.txt | uniq -u -f 3 -w 8  > uniq.txt

答案 3 :(得分:1)

$ awk 'NR==FNR{c[$4]++;next} c[$4]<2' file file
6   SNP_A_30018679  0   30018679    T   G
6   SNP_A_30018682  0   30018682    T   G
6   SNP_A_30018695  0   30018695    G   C

答案 4 :(得分:1)

awk中的另一个人:

$ awk '{$1=$1; a[$4]=a[$4] $0} END{for(i in a) if(gsub(FS,FS,a[i])==5) print a[i]}' file
6 SNP_A_30018679 0 30018679 T G
6 SNP_A_30018682 0 30018682 T G
6 SNP_A_30018695 0 30018695 G C

使用$4作为键来连接数组。如果有超过5个字段分隔符,则会复制重复项并且不会打印。

然而另一个版本是awk。它期望文件在第四个字段上排序。它不会将所有行存储在内存中,只有密钥(这可能也可以处理,因为密钥字段必须排序,以后可以修复)并一次运行:< / p>

$ cat ananother.awk
++seen[p[4]]==1 && NR>1 && p[4]!=$4 {  # seen count must be 1 and
    print prev                         # this and previous $4 must differ
    delete seen                        # is this enough really?
}
{ 
    q=p[4]                             # previous previous $4 for END
    prev=$0                            # previous is stored for printing
    split($0,p)                        # to get previous $4
} 
END {                                  # last record control
    if(++seen[$4]==1 && q!=$4) 
        print $0
}

执行命令

$ sort -k4,4 file | awk -f ananother.awk

答案 5 :(得分:0)

一种更简单的方法,

cat file.csv | cut -d, -f3,5,6,1 | sort -u > uniq.txt