我有一个很大的文件,很多行都是这样开头的:
22 16052167 rs375684679 A AAAAC . PASS DR2=0.02;AF=0.4728;IMP GT:DS在这些行中,DR2值的范围从0到1,我想提取那些包含大于0.8的DR2值的行。
我尝试过sed和awk两种解决方案,但似乎都不起作用……我尝试过以下几种方法:
grep "DR2=[0-1]\.[8-9]*" myfile发布于 2019-05-07 17:48:52
这将匹配值大于或等于0.8的行。如果您坚持使用严格大于,那么我将不得不添加一些复杂性,以防止0.8匹配。
grep 'DR2=\(1\|0\.[89]\)' myfile诀窍是您需要两个单独的子模式:一个匹配1或更大,一个匹配0.8或更大。
发布于 2019-05-07 20:32:14
grep -E 'DR2=\([1-9]\|0[.][89]\)'sed -n '/\([1-9]\|0[.][89]\)/p'awk '/\([1-9]\|0[.][89]\)/'这3种解决方案都基于单个正则表达式,并且都做同样的事情(参见Ruud HelderMan's solution)。
然而,使用awk,如果你的限制有点棘手,你可以做一个艺术检查。比方说,我希望DR2的值在0.53到1.39之间。
awk '! match($0,/DR2=/) { next }
{ val = substr($0,RSTART+RLENGTH)+0 }
( 0.53 < val) && ( val < 1.39 )'发布于 2019-05-08 00:19:20
每当您的数据中有tag=value对时,我发现最好首先在下面创建这些对(f[])的数组,然后您就可以通过它们的标记访问值。您没有提供任何0.8的输入来进行测试,因此使用您提供的数据:
$ awk '{split($8,t,/[=;]/); for (i=1; i in t; i+=2) f[t[i]]=t[i+1]} f["DR2"] > 0.01' file
22 16052167 rs375684679 A AAAAC . PASS DR2=0.02;AF=0.4728;IMP GT:DS或者使用标记和值的变量:
$ awk -v tag='DR2' -v val='0.8' '{split($8,t,/[=;]/); for (i=1; i in t; i+=2) f[t[i]]=t[i+1]} f[tag] > val' file
$
$ awk -v tag='DR2' -v val='0.01' '{split($8,t,/[=;]/); for (i=1; i in t; i+=2) f[t[i]]=t[i+1]} f[tag] > val' file
22 16052167 rs375684679 A AAAAC . PASS DR2=0.02;AF=0.4728;IMP GT:DS
$
$ awk -v tag='AF' -v val='0.4' '{split($8,t,/[=;]/); for (i=1; i in t; i+=2) f[t[i]]=t[i+1]} f[tag] > val' file
22 16052167 rs375684679 A AAAAC . PASS DR2=0.02;AF=0.4728;IMP GT:DS
$
$ awk -v tag='AF' -v val='0.5' '{split($8,t,/[=;]/); for (i=1; i in t; i+=2) f[t[i]]=t[i+1]} f[tag] > val' file
$或者使用复合条件:
$ awk '{split($8,t,/[=;]/); for (i=1; i in t; i+=2) f[t[i]]=t[i+1]}
(f["AF"] > 0.4) && (f["AF"] < 0.5) && (f["DR2"] >= 0.02)
' file
22 16052167 rs375684679 A AAAAC . PASS DR2=0.02;AF=0.4728;IMP GT:DS重点是,无论您想要对这些标记的值做什么比较,都是微不足道的,并且您不需要编写更多的代码来隔离和保存这些标记及其值。
https://stackoverflow.com/questions/56019584
复制相似问题