Извлечение строк с шаблоном строки и переменной - PullRequest
0 голосов
/ 07 мая 2019

У меня большой файл с множеством строк, начинающихся следующим образом:

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

Ответы [ 3 ]

4 голосов
/ 07 мая 2019

Соответствует строкам со значением, большим или равным 0,8.Если вы настаиваете на том, что строго больше чем, тогда мне придется добавить некоторую сложность, чтобы не дать совпадения 0,8.

grep 'DR2=\(1\|0\.[89]\)' myfile

Хитрость заключается в том, что вам нужно два отдельных подшаблона: один для соответствия 1 и больше, одинсоответствовать 0,8 и выше.

1 голос
/ 07 мая 2019

Когда в ваших данных есть пары тег = значение, я считаю, что лучше сначала создать массив этих пар (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

Дело в том, что любые сравнения, которые вы хотите выполнить со значениями этих тегов, являются тривиальными, и вам не нужно писать больше кода, чтобы изолировать и сохранить эти теги и их значения.

1 голос
/ 07 мая 2019
  • 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 )

Однако с помощью awk вы можете выполнить арифметическую проверку, если ваши ограничения немного сложнее.Допустим, я хочу, чтобы значение DR2 составляло от 0,53 до 1,39.

awk '! match($0,/DR2=/) { next }
     { val = substr($0,RSTART+RLENGTH)+0 }
     ( 0.53 < val) && ( val < 1.39 )'
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...