Awk 根据每行一列中的最高值筛选文件

Awk 根据每行一列中的最高值筛选文件,awk,Awk,我有以下文件: gene.100079.0.5.p3 transcript:OIS96097 82.2 169 30 0 1 169 4 172 1.3e-75 283.1 84.9 gene.100079.0.3.p1 transcript:OIS96097 82.2 169 30 0 1 169 4 172 1.3e-75 283.1 84.9 gene.100079.0.0.p1 transcript:OIS96097 82.2

我有以下文件:

gene.100079.0.5.p3  transcript:OIS96097 82.2    169 30  0   1   169 4   172 1.3e-75 283.1   84.9
gene.100079.0.3.p1  transcript:OIS96097 82.2    169 30  0   1   169 4   172 1.3e-75 283.1   84.9
gene.100079.0.0.p1  transcript:OIS96097 82.2    169 30  0   1   169 4   172 1.3e-75 283.1   86.7
gene.100080.0.3.p1  transcript:OIS96097 82.2    169 30  0   1   169 4   172 1.3e-75 283.1   99.9
gene.100080.0.0.p1  transcript:OIS96097 82.2    169 30  0   1   169 4   172 1.3e-75 283.1   99.9
chr11_pilon3.g3568.t1   transcript:OIS96097 82.2    169 30  0   1   169 4   172 1.3e-75 283.1   74.9
chr11_pilon3.g3568.t2   transcript:OIS96097 82.2    169 30  0   1   169 4   172 1.3e-75 283.1   76.7
上面的文件有一些类似的ID

gene.100079.0.5.p3
gene.100079.0.3.p1
gene.100079.0.0.p1
通过只保留
gene.100079
ID,ID变得相同。我想通过以下方式过滤上述文件:

  • chr11\u pilon3.g3568.t1=74.9
    。以
    chr
    开头的ID被排除在比较之外,并直接在输出中结束
  • gene.100079.0.0.p1=86.7
    和&
    gene.100079.0.5.p3=84.9
    =
    gene.100079.0.3.p1=84.9
    <代码>基因.100079.0.0.p1的值最高,因此应该在输出中
  • gene.100080.0.3.p1=99.9
    =
    gene.100080.0.0.p1=99.9
    。两个ID都有相同的值,因此都应该在输出中
但是,@RavinderSingh13和@anubhava的这个awk脚本返回了错误的结果

awk '{
   if (/^gene\./) {
      split($1, a, /\./)
      k = a[1] "." a[2]
    }
    else
       k = $1
}
!(k in max) || $13 >= max[k] {
   if(!(k in max))
      ord[++n] = k
   else if (max[k] == $13) {
      print
      next
   }
   max[k] = $13
   rec[k] = $0
}
END {
   for (i=1; i<=n; ++i)
      print rec[ord[i]]
}' file
作为输出,我希望得到:

chr11_pilon3.g3568.t1   transcript:OIS96097 82.2    169 30  0   1   169 4   172 1.3e-75 283.1   74.9
chr11_pilon3.g3568.t2   transcript:OIS96097 82.2    169 30  0   1   169 4   172 1.3e-75 283.1   76.7
gene.100079.0.0.p1  transcript:OIS96097 82.2    169 30  0   1   169 4   172 1.3e-75 283.1   86.7
gene.100080.0.3.p1  transcript:OIS96097 82.2    169 30  0   1   169 4   172 1.3e-75 283.1   99.9
gene.100080.0.0.p1  transcript:OIS96097 82.2    169 30  0   1   169 4   172 1.3e-75 283.1   99.9
我还试图修复如下所示,但无效:

awk '{
   if (/^gene\./) {
      split($1, a, /\./)
      k = a[1] "." a[2]
    }
    else
       k = $1
}
!(k in max) || $13 > max[k] {
   max[k]=$13; 
   line[k]=$0
}
END {
   for(i in line) 
      print line[i]
}'

提前感谢您,

这似乎工作正常,假设对数据进行了排序,以便在数据文件中将具有相同前两个名称组件的所有行分组在一起。组中这些行的顺序并不重要

经修订,问题现在希望以
chr
开头的行在不进行任何过滤的情况下传输到输出。这很容易实现-规则匹配
/^chr/
提供了该功能

#!/bin/sh

awk '
    function dump_memo()
    {
        if (memo_num > 0)
        {
            for (i = 0; i < memo_num; i++)
                print memo_line[i]
        }
    }
    /^chr/ { print; next }         # Do not process lines starting chr specially
    {
        split($1, a, ".")
        key = a[1] "." a[2]
        val = $NF
        # print "# " key " = " val " (memo_key = " memo_key ", memo_val = " memo_val ")"
        if (memo_key == key)
        {
            if (memo_val == val)
            {
                memo_line[memo_num++] = $0
            }
            else if (memo_val < val)
            {
                memo_val = val
                memo_num = 0
                memo_line[memo_num++] = $0
            }
        }
        else
        {
            dump_memo()
            memo_num = 0
            memo_line[memo_num++] = $0
            memo_key = key
            memo_val = val
        }
    }
    END { dump_memo() }' "$@"
这与请求的主要区别在于排序顺序。如果需要按排序的顺序排列数据,请通过
排序
管道输出脚本

修订后的脚本(使用
/^chr/
规则)是:


同样,如果您希望数据按特定顺序排列,请对输出应用
排序

请展示您自己的努力。很抱歉,我在规则中犯了一个错误,因为以
chr
开头的ID被排除在比较之外,并直接在输出中结束。我更新了我的问题。很抱歉,我在规则中犯了一个错误,因为以
chr
开头的ID被排除在比较之外,并且它们直接在输出中结束。我更新了我的问题。我更新了我的答案-并提供了更新的输出。如果您想在
chr11
行之前输出
gene.100080
,那么您需要做更多的工作-在
chr
规则中调用
dump\u memo()
,然后再打印行并转换
memo*
数据(将
memo_num
设置为零,并将
memo_key
memo_val
设置为空字符串-可能全部在函数中,也可以选择但最好进行一些其他调整).OTOH,如果你要对输出进行排序,打印的顺序并不重要。请以后小心-第一次把问题的细节弄清楚。谢谢,我会的。我不介意输出顺序,因为我可以使用
| sort-k1
YW。注意
sort-k1
在功能上与
sort
相同。
#!/bin/sh

awk '
    function dump_memo()
    {
        if (memo_num > 0)
        {
            for (i = 0; i < memo_num; i++)
                print memo_line[i]
        }
    }
    /^chr/ { print; next }         # Do not process lines starting chr specially
    {
        split($1, a, ".")
        key = a[1] "." a[2]
        val = $NF
        # print "# " key " = " val " (memo_key = " memo_key ", memo_val = " memo_val ")"
        if (memo_key == key)
        {
            if (memo_val == val)
            {
                memo_line[memo_num++] = $0
            }
            else if (memo_val < val)
            {
                memo_val = val
                memo_num = 0
                memo_line[memo_num++] = $0
            }
        }
        else
        {
            dump_memo()
            memo_num = 0
            memo_line[memo_num++] = $0
            memo_key = key
            memo_val = val
        }
    }
    END { dump_memo() }' "$@"
gene.100079.0.0.p1  transcript:OIS96097 82.2    169 30  0   1   169 4   172 1.3e-75 283.1   86.7
gene.100080.0.3.p1  transcript:OIS96097 82.2    169 30  0   1   169 4   172 1.3e-75 283.1   99.9
gene.100080.0.0.p1  transcript:OIS96097 82.2    169 30  0   1   169 4   172 1.3e-75 283.1   99.9
chr11_pilon3.g3568.t2   transcript:OIS96097 82.2    169 30  0   1   169 4   172 1.3e-75 283.1   76.7
gene.100079.0.0.p1  transcript:OIS96097 82.2    169 30  0   1   169 4   172 1.3e-75 283.1   86.7
chr11_pilon3.g3568.t1   transcript:OIS96097 82.2    169 30  0   1   169 4   172 1.3e-75 283.1   74.9
chr11_pilon3.g3568.t2   transcript:OIS96097 82.2    169 30  0   1   169 4   172 1.3e-75 283.1   76.7
gene.100080.0.3.p1  transcript:OIS96097 82.2    169 30  0   1   169 4   172 1.3e-75 283.1   99.9
gene.100080.0.0.p1  transcript:OIS96097 82.2    169 30  0   1   169 4   172 1.3e-75 283.1   99.9