вести записи fast, которые имеют 2 совпадения значений OX - PullRequest
1 голос
/ 03 марта 2020

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

>sp|rin-1 ghsfdhjkuesl OX=10116 GN=Cdh1 PE=1 SV=1|sp|P10287|ghsfdjdeosd gdhkhs OX=10090 GN=Cdh3 PE=1 SV=2
WRDTANWLEINPETGVISTRAEMDREDSEHVKNSTYTALIIATDDGSPIATGTGTLLLVLSDVNDNAPIPEPRNMQFCQRNPKPHVITILDPDLPP
>sp|erin-1 ghsfdshkd OX=10116 GN=Cdh1 PE=1 SV=1|sp|P22223|CADH3_HUMAN Cadherin-3 OX=9606 GN=CDH3 PE=1 SV=2
ESYPTYTLVVQAADLQGEGLSTTAKAVITVKDINDNAPIFNPSTYLQCAASEPCRAVFREAEVTLEAGGAEQEPGQALGKVFMGCPGQEPALFSTD
>sp|n-1 ghsfd OX=10116 GN=Cdh1 PE=1 SV=1|tr|F1LMI3|ghsfdhsj dghe OX=10116 GN=Cdh3 PE=4 SV=3
MGARCRSFSALLLLLQVSSWLCQQPESESDSCRPGFSSEVYTFLVPERHLERGHILGRVKFEGCTGRPRTAFFSEDSRFKVSTDGVITVKRHLKLH

Я хочу хранить только те записи, в которых есть два совпадения значений OX, следовательно, желаемый вывод должен выглядеть следующим образом:

>sp|n-1 ghsfd OX=10116 GN=Cdh1 PE=1 SV=1|tr|F1LMI3|OX=10116 GN=Cdh3 PE=4 SV=3
MGARCRSFSALLLLLQVSSWLCQQPESESDSCRPGFSSEVYTFLVPERHLERGHILGRVKFEGCTGRPRTAFFSEDSRFKVSTDGVITVKRHLKLH

Код, который я пробовал, следующий:

awk -v p="OX=" 'FNR==1{x=0}{x+=gsub(p,p);if(x>2){print $line}}' test.fasta

Ответы [ 5 ]

3 голосов
/ 03 марта 2020

Как насчет этого, без использования l oop. Не могли бы вы попробовать следующее. Подробное объяснение будет добавлено через несколько минут.

awk '
match($0,/OX=[0-9]+/){
  val=substr($0,RSTART,RLENGTH)
  if(gsub(val,"&")==2){
    print
    found=1
  }
  val=""
  next
}
found{
  found=""
  print
}
' Input_file

ИЛИ небольшое редактирование в вышеупомянутом решении, где удаляется val="" часть согласно @Quasimodo комментарию:

awk '
match($0,/OX=[0-9]+/){
  val=substr($0,RSTART,RLENGTH)
  if(gsub(val,"&")==2){
    print
    found=1
  }
  next
}
found{
  found=""
  print
}
' Input_file

Объяснение: Добавление подробного пояснения к приведенному выше коду.

awk '                               ##Starting awk program from here.
match($0,/OX=[0-9]+/){              ##Using match function to match OX= digits in current line.
  val=substr($0,RSTART,RLENGTH)     ##Creating variable val whose value is sub-string of value of current line starts from RSTART till value of RLENGTH.
  if(gsub(val,"&")==2){             ##Checking condition if value of Global substitutions is equal to 2 then do following.
    print                           ##Printing the current line.
    found=1                         ##Setting variable found value as 1 here.
  }
  val=""                            ##Nullifying variable val here.
  next                              ##next will skip all further statements from here.
}
found{                              ##Checking condition if variable found is NOT NULL then do following.
  found=""                          ##Nullifying variable found here.
  print                             ##Printing current line here.
}
'  Input_file                       ##Mentioning Input_file name here.


РЕДАКТИРОВАТЬ: ПРИМЕЧАНИЕ, этот код пытается охватить крайний случай, если чьи-либо сэмплы точно такие же, как показано OP, то приведенные выше коды должны быть достаточно хорошими.

Пытаясь охватить крайний случай, упомянутый @kvantour в комментариях, немного изменил регулярное выражение, где перед ним следует проверять, например, OX, за которым следует пробел.

awk '
match($0,/\s+OX=[0-9]+\s+/){
  val=substr($0,RSTART,RLENGTH)
  if(gsub(val,"&")==2){
    print
    found=1
  }
  val=""
  next
}
found{
  found=""
  print
}
'  Input_file
2 голосов
/ 03 марта 2020

Я придумал этот awk скрипт, который, кажется, работает.

awk '
    printnext == 1 {                          #Prints the line after the line w 2 matches
        print;
        printnext=0;
    }
    match($0, /OX=[0-9]*/) {                  #Looks for OX=numbers
        id=substr($0,RSTART,RLENGTH);         #Saves it to id
        c=0;
        for (i=1;i<=NF;i++){                  #Looks for two occurrences of id in line
            if ($i==id){
                c=c+1;
                if (c==2) {print;printnext=1}
            }
        }
    }
' test.fasta
1 голос
/ 04 марта 2020

В GNU awk вы можете использовать patsplit и делить на желаемый контент против некоторого разделителя.

Дано:

$ cat test.fasta
>sp|rin-1 ghsfdhjkuesl OX=10116 GN=Cdh1 PE=1 SV=1|sp|P10287|ghsfdjdeosd gdhkhs OX=10090 GN=Cdh3 PE=1 SV=2
WRDTANWLEINPETGVISTRAEMDREDSEHVKNSTYTALIIATDDGSPIATGTGTLLLVLSDVNDNAPIPEPRNMQFCQRNPKPHVITILDPDLPP
>sp|erin-1 ghsfdshkd OX=10116 GN=Cdh1 PE=1 SV=1|sp|P22223|CADH3_HUMAN Cadherin-3 OX=9606 GN=CDH3 PE=1 SV=2
ESYPTYTLVVQAADLQGEGLSTTAKAVITVKDINDNAPIFNPSTYLQCAASEPCRAVFREAEVTLEAGGAEQEPGQALGKVFMGCPGQEPALFSTD
>sp|n-1 ghsfd OX=10116 GN=Cdh1 PE=1 SV=1|tr|F1LMI3|ghsfdhsj dghe OX=10116 GN=Cdh3 PE=4 SV=3
MGARCRSFSALLLLLQVSSWLCQQPESESDSCRPGFSSEVYTFLVPERHLERGHILGRVKFEGCTGRPRTAFFSEDSRFKVSTDGVITVKRHLKLH

Вы можете разделить и захватить пары значений, в этом случае OX=:

$ awk -v RS=$'>' '{
             cnt=patsplit($0, arr, "OX=[0-9]+") 
             if (cnt==2 && arr[1]==arr[2]) 
                printf ">%s", $0
            }' test.fasta   
>sp|n-1 ghsfd OX=10116 GN=Cdh1 PE=1 SV=1|tr|F1LMI3|ghsfdhsj dghe OX=10116 GN=Cdh3 PE=4 SV=3
MGARCRSFSALLLLLQVSSWLCQQPESESDSCRPGFSSEVYTFLVPERHLERGHILGRVKFEGCTGRPRTAFFSEDSRFKVSTDGVITVKRHLKLH
0 голосов
/ 04 марта 2020

Очень быстрым способом было бы сделать что-то вроде этого:

awk '/^>/{p=0;delete a
          for(i=1;i<=NF;++i) a[$i]++
          for(i in a) if (i ~ /^OX=/ && a[i]>1) p=1
         }
     p' file

Это будет соответствовать случаям, таким как:

> foobar OX=1 OX=2 OX=3 OX=1
ABCDEF

Немного более оптимизирован, если вы заботитесь только о Строка OX=, вы можете сделать:

awk '/^>/{p=0;delete a
          for(i=1;i<=NF;++i) if($i ~ /^OX=/) a[$i]++
          for(i in a) if (a[i]>1) p=1
         }
     p' file
0 голосов
/ 04 марта 2020
awk -F'[O][X][=]' '{a=$0; gsub(/ .*/,"",$2) ; gsub(/ .*/,"",$3) ;  if ($2==$3) print a }'

Демо

:>cat regular_expressions_are_greedy.txt
>sp|rin-1 ghsfdhjkuesl OX=10116 GN=Cdh1 PE=1 SV=1|sp|P10287|ghsfdjdeosd gdhkhs OX=10090 GN=Cdh3 PE=1 SV=2WRDTANWLEINPETGVISTRAEMDREDSEHVKNSTYTALIIATDDGSPIATGTGTLLLVLSDVNDNAPIPEPRNMQFCQRNPKPHVITILDPDLPP
>sp|erin-1 ghsfdshkd OX=10116 GN=Cdh1 PE=1 SV=1|sp|P22223|CADH3_HUMAN Cadherin-3 OX=9606 GN=CDH3 PE=1 SV=2ESYPTYTLVVQAADLQGEGLSTTAKAVITVKDINDNAPIFNPSTYLQCAASEPCRAVFREAEVTLEAGGAEQEPGQALGKVFMGCPGQEPALFSTD
>sp|n-1 ghsfd OX=10116 GN=Cdh1 PE=1 SV=1|tr|F1LMI3|ghsfdhsj dghe OX=10116 GN=Cdh3 PE=4 SV=3MGARCRSFSALLLLLQVSSWLCQQPESESDSCRPGFSSEVYTFLVPERHLERGHILGRVKFEGCTGRPRTAFFSEDSRFKVSTDGVITVKRHLKLH
:>awk -F'[O][X][=]' '{a=$0; gsub(/ .*/,"",$2) ; gsub(/ .*/,"",$3) ;  if ($2==$3) print a }' regular_expressions_are_greedy.txt
>sp|n-1 ghsfd OX=10116 GN=Cdh1 PE=1 SV=1|tr|F1LMI3|ghsfdhsj dghe OX=10116 GN=Cdh3 PE=4 SV=3MGARCRSFSALLLLLQVSSWLCQQPESESDSCRPGFSSEVYTFLVPERHLERGHILGRVKFEGCTGRPRTAFFSEDSRFKVSTDGVITVKRHLKLH
:>

Объяснение:

awk -F'[O][X][=]'  <---  Setting field separator as  "OX="
'{
a=$0; <-- Saving input record in variable a. ($0 = Means whole records)
gsub(/ .*/,"",$2) ; <-- Removing all character after space from column 1 
gsub(/ .*/,"",$3) ;  <-- Removing all character after space from column 2
if ($2==$3) <-- Checking if 2 values are equal. 
print a 
}'
...