我有一个很大的文件,很多行都是这样的:
22 16052167 rs375684679 A AAAAC . PASS DR2=0.02;AF=0.4728;IMP GT:DS
在这些行中,DR2
值的范围是0到1,我想提取包含DR2
值大于0.8的行。
我已经尝试过sed
或awk
两种解决方案,但似乎都没有用……我尝试了以下方法:
grep "DR2=[0-1]\.[8-9]*" myfile
答案 0 :(得分:4)
这将匹配值大于或等于 0.8的行。如果您坚持严格大于,那么我将不得不增加一些复杂性以防止0.8匹配。
grep 'DR2=\(1\|0\.[89]\)' myfile
诀窍在于,您需要两个单独的子模式:一个子模式可以匹配1个或更大,一个子模式可以匹配0.8个或更大。
答案 1 :(得分:1)
grep: grep -E 'DR2=\([1-9]\|0[.][89]\)'
sed: sed -n '/\([1-9]\|0[.][89]\)/p'
awk: 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 )'
答案 2 :(得分:1)
每当您的数据中有标记=值对时,我发现最好首先在下面创建一个由这些配对(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
要点是,您想要对这些标记的值进行比较是微不足道的,并且您无需编写更多代码来隔离并保存这些标记及其值。