Compare dois arquivos de texto e encontre linhas correspondentes

4

Eu tenho dois arquivos A e B. A se parece com isso (4 a 6 linhas):

GAGA
CAGA
GGGT
TATT

o arquivo B é realmente um arquivo grande com milhares de linhas, aqui está um pequeno exemplo:

AAATGTCAAGAGACAGAAATGTCAAGAGGGT
AAGGGGGTTTATAATCATAAATCAAAGAAAT
ATATACAGAAATGTCAAGAGACAGAAATGTC
TCAAGAGACAGAAATGTCAAGAGGGTCTATA
AAGAGGGTCTATAATCATAAATCAAAGAAAT
AAGAGGGTCTATAATCATAAATCAAAGAAAT
ATACAGAAATGTCAAAACAGAAATGTCAAGG
ATATACAGAATATACAGAAATGTCAAGTTAT
ACAGAATATACAGAAATGTCAAGTTATATAC
ATATACAGAAATGTCAAGAGACAGAAATGTC
TCAGAATATAGTATTCTATTATATACAGAAA
AATATAGTATTCTATTATATACAGAAATGTC
GAATATACAGAAATGTCAAGTTATATACAGA
TATACAGAATATAGTATTCTATTATATACAG
CAGAATATAGTATTCTATTATATACAGAATA
AGTTATATACAGAATATAGTATTCTATTATA
TACAGAATATAGTATTCTATTATATACAGAA
CAGAAATGTCAAGTTATATACAGAATATAGT

Eu preciso pesquisar todas as strings no arquivo A em todas as linhas do arquivo B e recuperar as primeiras 10 linhas do arquivo B que contêm cada string de A. Eu tentei o grep e o awk, mas não com bons resultados. Obrigado

    
por Alejandro 07.03.2014 / 19:15

4 respostas

5

Como seus padrões são de quatro a seis linhas, por que não usá-los em um padrão OR? Um exemplo que limita a 10 correspondências que operam em um segundo arquivo "bigDNA.txt":

grep -E 'GAGA|CAGA|GGGT|TATT' -m 10 bigDNA.txt

Isso evitará que você digite manualmente os padrões do arquivo patt.txt . Ele une as linhas por | (anexar | a cada linha, remover nova linha, remover | ):

grep -E "$(sed 's#$#|#' patt.txt | tr -d '\n' | sed 's#|$##')" -m 10 bigDNA.txt
    
por 07.03.2014 / 19:40
2

Você tentou iterar pelo "arquivo A" com um while loop?

while read string
 do grep "$string" file-B | head -10
done < file-A

Ou em uma linha:

while read string; do grep "$string" file-B | head -10; done < file-A
    
por 07.03.2014 / 19:29
1

Aqui está um roteiro que poderá ser lido.

FIRSTFILE contém 1 item por linha (sem espaços extras, etc) BIGFILE contém a lista grande que você quer combinar

awk -F, '
  BEGIN{
     regexp="__NOTMATCHING__"
     linematched=0
     while(( getline line<"FIRSTFILE") > 0 ) {
        nb_items[line]=0; #initialise a counter in items["...."]
        regexp=regexp"|"line  #we create a "egrep-like" regexp matching each item
     }

  }

#main : read each line. 
#           - save each matching lines. 
#           - and increment each corresponding counters. 
  {  if ( $0 ~ regexp ) {
        matchinglines[++linematched]=$0
        for ( item in nb_items ) {
           #for each matching item, we also increment that item s number
           if ( $0 ~ item ) { 
              nb_items[item]++ ; 
           }
        }
     }
  }

END  {  #at the end, we print all items which have nb_item[item]>=10
        for ( item in nb_items ) {
           if (nb_items[item] >= 10) {
              print "for this item:",item
              for (i;i<=linematched;i++) {
                 if ( matchinglines[i] ~ item ) {
                    print matchinglines[i] ; 
                 }
              }
           }
        }
     }
   ' BIGFILE
    
por 07.03.2014 / 19:55
1

Isso imprimirá as primeiras 10 linhas que corresponderem a qualquer uma das suas strings:

grep -m 10 -Ff motifs sequence.fa 

Este lerá cada motivo e imprimirá as dez primeiras linhas que o math, então ele imprimirá 10 linhas para cada motivo:

while read mot; do grep -m 10 "$mot" sequence.fa; done < motifs

No entanto, parece uma sequência de DNA, o que significa que as quebras de linha são completamente arbitrárias e você pode ter correspondências assim:

ACTG GA
GA

Com essas abordagens, o GAGA acima não será contado como uma correspondência e provavelmente não é o que você deseja. Em vez disso, sugiro que você coloque tudo em uma única linha antes de pesquisar. Já que você está pedindo linhas correspondentes, eu suponho que você queira cada um desses motivos em seu contexto. Então, para fazer isso corretamente, combinando motivos que são divididos em novas linhas, primeiro transforme seu arquivo em TBL . Eu tenho usado o mesmo pequeno script awk escrito por um colega (obrigado Pep) por anos:

#!/bin/sh
gawk '{
        if (substr($1,1,1)==">")
        if (NR>1)
                    printf "\n%s\t", substr($0,2,length($0)-1)
        else 
            printf "%s\t", substr($0,2,length($0)-1)
        else 
                printf "%s", $0
}END{printf "\n"}'  "$@"

Salve o script acima como FastaToTbl em algum lugar no seu $PATH ( /usr/local/bin por exemplo) e torne-o executável ( chmod a+x /usr/local/bin/FastaToTbl ). Então, você pode simplesmente canalizar sequências de formato FASTA e imprimirá .tbl format, onde o identificador e a sequência estão todos na mesma linha.

Então, quando você tiver o FastaToTbl configurado, poderá executar:

while read mot; 
do 
    FastaToTbl sequence.fa | grep -Po ".{10}$mot.{10}" | head -n 10 
done < motifs   

As opções acima darão as 10 primeiras correspondências para cada padrão e também corresponderão a motivos divididos em novas linhas. Ele também imprimirá os 10 caracteres de cada lado do padrão correspondente, alterará o {10} para outro número para controlar esse comportamento.

    
por 08.03.2014 / 04:10