过滤文件以查找在一列中匹配但在另一列中不同的行

Filter a file to find rows that match in one column but differ in another column

我想过滤一个文件,以便我可以获得在第 1 列中匹配但在第 2 列中不匹配的行。在以下示例中:

00b27c71-a833-4605-9fb3-a2714ac98092    ENST00000352983.6   157 60  16
00d77e65-466e-4fe6-ad0f-bc6b3f44af75    ENST00000367142.4   130 12  4
00d77e65-466e-4fe6-ad0f-bc6b3f44af75    ENST00000367142.4   8   60 0
00b27c71-a833-4605-9fb3-a2714ac98091    ENST00000258424.2   12  60 2048
00b27c71-a833-4605-9fb3-a2714ac98091    ENST00000352983.6   157 60  16
00d77e65-466e-4fe6-ad0f-bc6b3f44af74    ENST00000367142.5   130 12  4
00d77e65-466e-4fe6-ad0f-bc6b3f44af74    ENST00000367142.7   8   60 0
00d77e65-466e-4fe6-ad0f-bc6b3f44af74    ENST00000258424.2   8   60 0

我想在第 1 列中找到恰好出现两次但在第 2 列中不匹配的整体,即应忽略组合 column1、column2 中的重复项。所以预期的输出将是:

00b27c71-a833-4605-9fb3-a2714ac98091    ENST00000258424.2   12  60 2048
00b27c71-a833-4605-9fb3-a2714ac98091    ENST00000352983.6   157 60  16

第 3、4、5 等列中的内容对于过滤并不重要,但我确实需要保留这些信息。

我还需要从读取文件和保留 header 所必需的另一个输出中导入它。所以我需要以下格式的内容:

samtools view -h file.bam | code that I need > results.bam

我试过好几个版本的awk,都没有用。任何帮助将不胜感激。

编辑: 根据 OP,它应该从 awk 中单独读取,所以添加它 not.w

your_command |  awk '
{
  a[]++;
  b[ FS ]++;
  c[ FS ]=[=10=]
}
END{
  for(i in a){
    for(j in b){
      split(j,array," ");
      if(a[i]==2 && b[j]==1 && i==array[1]){  print c[j]  }
    }
}}'

能否请您尝试关注,如果对您有帮助,请告诉我。

awk 'FNR==NR{a[]++;b[ FS ]++;next} a[]==2 && b[ FS ]==1'  Input_file  Input_file

我相信你追求的是:

awk '!( FS  in a) { b[]++; a[ FS ]=[=10=] }
     END { for(i in a) {[=10=]=i; if (b[]==2) print a[i] } }' file

这输出:

00b27c71-a833-4605-9fb3-a2714ac98091    ENST00000352983.6   157 60  16
00b27c71-a833-4605-9fb3-a2714ac98091    ENST00000258424.2   12  60 2048

它本质上做的是检查组合 FS 是否在数组 a 中。如果不是,请跟踪 b[]</code> 的计数并将整行存储在 <code>a[ FS ] 中。最后,如果计数正确,则打印 a[i] 。备注 b 的密钥是通过将密钥 i 重新分配给 [=24=] 获得的。这将重新定义字段 </code> 和 <code> 并且 </code> 是您想要的键。</p> <p><strong>注意:</strong>上面的脚本不一定会跟踪顺序,因为数组遍历是以未指定的顺序完成的。如果你想保持顺序,你需要跟踪行索引:</p> <pre><code>awk '!( FS in a) { b[]++; a[ FS ]=[=12=]; c[NR]= FS } END { for(i=1;i<=NR;++i) if(i in c) { [=12=]=c[i]; if (b[]==2) print a[[=12=]]} }' file

输出:

00b27c71-a833-4605-9fb3-a2714ac98091    ENST00000258424.2   12  60 2048
00b27c71-a833-4605-9fb3-a2714ac98091    ENST00000352983.6   157 60  16

旧答案:

awk '!( in a) { a[]=; b[]=[=14=]; next }
     !match(,a[]){a[]=a[] FS ; b[]=b[] ORS [=14=]}
     END { for (i in a) if (gsub(FS,FS,a[i]) == 1) print b[i] }' file

这输出:

00b27c71-a833-4605-9fb3-a2714ac98091    ENST00000258424.2   12  60 2048
00b27c71-a833-4605-9fb3-a2714ac98091    ENST00000352983.6   157 60  16

它本质上做的是跟踪两个数组(ab),这两个数组都由第一列索引。如果数组 a 不包含列 </code> 的元素,则将其添加到字符串 <code>a[]。它还将整行存储在 b[] 中,由 ORS 分隔。 最后我们统计a[i]中有多少个字段,如果是两个就打印b[i].