提取具有字符串和可变数字模式的行

时间:2019-05-07 09:30:38

标签: grep

我有一个很大的文件,很多行都是这样的:

22 16052167 rs375684679 A AAAAC . PASS DR2=0.02;AF=0.4728;IMP GT:DS

在这些行中,DR2值的范围是0到1,我想提取包含DR2值大于0.8的行。

我已经尝试过sedawk两种解决方案,但似乎都没有用……我尝试了以下方法:

grep "DR2=[0-1]\.[8-9]*" myfile

3 个答案:

答案 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

要点是,您想要对这些标记的值进行比较是微不足道的,并且您无需编写更多代码来隔离并保存这些标记及其值。