使用两个条件过滤文件

使用两个条件过滤文件

我有以下文件

> head map.stats
ID=NbD053289.1.mrna1;Name=NbD053289.1;Parent=NbD053289.1.path1;coverage=100.0;identity=100.0;matches=702;mismatches=0;indels=0;unknowns=0
ID=NbD053288.1.mrna1;Name=NbD053288.1;Parent=NbD053288.1.path1;coverage=100.0;identity=99.8;matches=482;mismatches=1;indels=0;unknowns=0
ID=NbD053287.1.mrna1;Name=NbD053287.1;Parent=NbD053287.1.path1;coverage=100.0;identity=94.1;matches=738;mismatches=0;indels=46;unknowns=0
ID=NbD053281.1.mrna1;Name=NbD053281.1;Parent=NbD053281.1.path1;coverage=99.3;identity=99.1;matches=1476;mismatches=14;indels=0;unknowns=0

我想过滤掉$identity >= 95 && $coverage == 100这样我就可以得到这个输出

ID=NbD053289.1.mrna1;Name=NbD053289.1;Parent=NbD053289.1.path1;coverage=100.0;identity=100.0;matches=702;mismatches=0;indels=0;unknowns=0
ID=NbD053288.1.mrna1;Name=NbD053288.1;Parent=NbD053288.1.path1;coverage=100.0;identity=99.8;matches=482;mismatches=1;indels=0;unknowns=0

我尝试过grep -oP '(?<=identity=).*?(?=;)' map.stats | awk '$1 >= 99',但并没有让我走得太远。怎么可能进行这种过滤呢?

提前谢谢你

答案1

这是另一种方法:

$ awk -F'[;=]' '$10>=95 && $8 == 100' file
ID=NbD053289.1.mrna1;Name=NbD053289.1;Parent=NbD053289.1.path1;coverage=100.0;identity=100.0;matches=702;mismatches=0;indels=0;unknowns=0
ID=NbD053288.1.mrna1;Name=NbD053288.1;Parent=NbD053288.1.path1;coverage=100.0;identity=99.8;matches=482;mismatches=1;indels=0;unknowns=0

技巧是将字段分隔符设置为;or =(这就是-F'[;=]'作用)。那么, 的值identity将是第 10 个字段, 的值coverage将是第 8 个字段。由于awk当表达式计算结果为 true 时 的默认操作是打印当前行,这意味着$10>=95 && $8 == 100将打印与这两个条件匹配的任何行。


实际上,您也可以使用 GNU 执行此操作grep,但您不需要该-o选项,因为您需要整行,并且没有理由使用后向查找。您所需要的只是定义范围。由于您需要从95100( >=95) 的值,这意味着您需要 a后跟和9之间的任意一个数字,或者 a :59100

$ grep  -P 'coverage=100.0.*identity=(9[5..9]|100)' file 
ID=NbD053289.1.mrna1;Name=NbD053289.1;Parent=NbD053289.1.path1;coverage=100.0;identity=100.0;matches=702;mismatches=0;indels=0;unknowns=0
ID=NbD053288.1.mrna1;Name=NbD053288.1;Parent=NbD053288.1.path1;coverage=100.0;identity=99.8;matches=482;mismatches=1;indels=0;unknowns=0

请注意,我假设同一性不能采用大于 100 的值,这似乎是一个安全的假设,因为您可能正在考虑序列守恒,并且您无法获得比 100% 相同更相似的结果。

答案2

首先让我们使用将字段转换为数字

awk -F= 'NR==1 { for(i=1;i<=NF;i++) printf "%2d %s\n",i,$i ;}' file
 1 ID
 2 NbD053289.1.mrna1;Name
 3 NbD053289.1;Parent
 4 NbD053289.1.path1;coverage
 5 100.0;identity
 6 100.0;matches
 7 702;mismatches
 8 0;indels
 9 0;unknowns
10 0

所以覆盖范围是 5,身份是 6

接下来,我们不能直接使用 awk,==因为它会匹配字符串,所以我们使用 +1 转换为数字。

这个产量

awk -F= '$6+1>96 && ($5+1) == 101' file
ID=NbD053289.1.mrna1;Name=NbD053289.1;Parent=NbD053289.1.path1;coverage=100.0;identity=100.0;matches=702;mismatches=0;indels=0;unknowns=0
ID=NbD053288.1.mrna1;Name=NbD053288.1;Parent=NbD053288.1.path1;coverage=100.0;identity=99.8;matches=482;mismatches=1;indels=0;unknowns=0

在哪里

  • -F=告诉 awk 用作=分隔符
  • $6+1>96如上所述转换为数字并过滤

相关内容