Grep não retorna correspondências idênticas do awk pipe

1

Estou tentando identificar todas as linhas em comum com base na primeira coluna de um arquivo. Estou usando o seguinte comando:

awk '{print $1}' File1 | fgrep -wf - File2 >Out

Arquivo1:

M01605:153:000000000-B55NK:1:1101:10003:14536   chr1    150129998   A   Rev 18
M01605:153:000000000-B55NK:1:1101:10007:14573   chr17   44166311    C   38  44166311
M01605:153:000000000-B55NK:1:1101:10007:14573   chr17   44166500    G   Rev 34
M01605:153:000000000-B55NK:1:1101:10009:9160    chr8    16716272    G   35  16716395
M01605:153:000000000-B55NK:1:1101:10009:9160    chr8    16716336    A   37  16716337
M01605:153:000000000-B55NK:1:1101:10009:9160    chr8    16716336    A   38  16716459
M01605:153:000000000-B55NK:1:1101:10010:14111   chr8    89574844    A   38  89574844
M01605:153:000000000-B55NK:1:1101:10010:19939   chr3    181151945   T   36  181151945
M01605:153:000000000-B55NK:1:1101:10011:22802   chr17   43984669    A   34  43984765
M01605:153:000000000-B55NK:1:1101:10011:22802   chr17   43984669    A   38  43984689

Arquivo2:

M01605:153:000000000-B55NK:1:1101:10003:14536   2:N:0:1 GTTTGCGCCGATGTA 
M01605:153:000000000-B55NK:1:1101:10003:4882    2:N:0:1 GCACTGTAAAAAGTA 
M01605:153:000000000-B55NK:1:1101:10007:14573   2:N:0:1 GGGGATAAGCGTTGC 
M01605:153:000000000-B55NK:1:1101:10007:5336    2:N:0:1 GTGTTTGTGTAGCTA 
M01605:153:000000000-B55NK:1:1101:10008:14477   2:N:0:1 GGGCGGAGGTGAAGA 
M01605:153:000000000-B55NK:1:1101:10009:18543   2:N:0:1 AGTTCGAGCGCAGTG 
M01605:153:000000000-B55NK:1:1101:10009:9160    2:N:0:1 CAGAAGAGGTAATGT 
M01605:153:000000000-B55NK:1:1101:10010:14111   2:N:0:1 CTGCGTACTGATAGC 
M01605:153:000000000-B55NK:1:1101:10010:19939   2:N:0:1 TCCGTGGTGCCGGCA 
M01605:153:000000000-B55NK:1:1101:10011:22802   1:N:0:1 TGAGTTCGGATAAAG 

Fora:

M01605:153:000000000-B55NK:1:1101:10003:14536 2:N:0:1   GTTTGCGCCGATGTA 
M01605:153:000000000-B55NK:1:1101:10007:14573 2:N:0:1   GGGGATAAGCGTTGC 
M01605:153:000000000-B55NK:1:1101:10009:9160 2:N:0:1    CAGAAGAGGTAATGT 
M01605:153:000000000-B55NK:1:1101:10010:14111 2:N:0:1   CTGCGTACTGATAGC 
M01605:153:000000000-B55NK:1:1101:10010:19939 2:N:0:1   TCCGTGGTGCCGGCA 
M01605:153:000000000-B55NK:1:1101:10011:22802 1:N:0:1   TGAGTTCGGATAAAG 

Esperado Fora:

M01605: 153: 000000000-B55NK: 1: 1101: 10003: 14536 2: N: 0: 1 GTTTGCGCCGATGTA M01605: 153: 000000000-B55NK: 1: 1101: 10007: 14573 2: N: 0: 1 GGGGATAAGCGTTGC M01605: 153: 000000000-B55NK: 1: 1101: 10007: 14573 2: N: 0: 1 GGGGATAAGCGTTGC M01605: 153: 000000000-B55NK: 1: 1101: 10009: 9160 2: N: 0: 1 CAGAAGAGGTAATGT M01605: 153: 000000000-B55NK: 1: 1101: 10009: 9160 2: N: 0: 1 CAGAAGAGGTAATGT M01605: 153: 000000000-B55NK: 1: 1101: 10009: 9160 2: N: 0: 1 CAGAAGAGGTAATGT M01605: 153: 000000000-B55NK: 1: 1101: 10010: 14111 2: N: 0: 1 CTGCGTACTGATAGC M01605: 153: 000000000-B55NK: 1: 1101: 10010: 19939 2: N: 0: 1 TCCGTGGTGCCGGCA M01605: 153: 000000000-B55NK: 1: 1101: 10011: 22802 1: N: 0: 1 TGAGTTCGGATAAAG

Observe que as linhas em negrito estão faltando na saída real gerada e são o que eu quero estar no arquivo de saída.

Parece que o grep está funcionando corretamente, mas condensando todas as linhas idênticas em apenas uma linha de saída. Alguma sugestão?

    
por William Law 14.09.2017 / 23:01

3 respostas

0

É exatamente para isso que o comando join é feito: ele une dois arquivos com base em um campo comum:

$ awk '{print $1}' File1 | join - File2

M01605:153:000000000-B55NK:1:1101:10003:14536 2:N:0:1 GTTTGCGCCGATGTA 
M01605:153:000000000-B55NK:1:1101:10007:14573 2:N:0:1 GGGGATAAGCGTTGC 
M01605:153:000000000-B55NK:1:1101:10007:14573 2:N:0:1 GGGGATAAGCGTTGC 
M01605:153:000000000-B55NK:1:1101:10009:9160 2:N:0:1 CAGAAGAGGTAATGT 
M01605:153:000000000-B55NK:1:1101:10009:9160 2:N:0:1 CAGAAGAGGTAATGT 
M01605:153:000000000-B55NK:1:1101:10009:9160 2:N:0:1 CAGAAGAGGTAATGT 
M01605:153:000000000-B55NK:1:1101:10010:14111 2:N:0:1 CTGCGTACTGATAGC 
M01605:153:000000000-B55NK:1:1101:10010:19939 2:N:0:1 TCCGTGGTGCCGGCA 
M01605:153:000000000-B55NK:1:1101:10011:22802 1:N:0:1 TGAGTTCGGATAAAG 
M01605:153:000000000-B55NK:1:1101:10011:22802 1:N:0:1 TGAGTTCGGATAAAG 

Seus arquivos podem ser classificados numericamente, mas não alfabeticamente, como esperado por join . Se join estiver reclamando, modifique levemente o comando acima para classificar a entrada com GNU sort :

$ awk '{print $1}' File1 | sort | join - <(sort -k1,1 --stable File2)

Como seu segundo arquivo parece ter linhas duplicadas (veja os comentários), você pode querer alterar o segundo comando sort para sort -k1,1 --stable --unique File2 (ainda que você esteja usando o GNU sort , use uniq ). / p>     

por 14.09.2017 / 23:23
2

Conforme eu interpreto sua saída desejada, você deseja que as linhas no Arquivo2 sejam repetidas quantas vezes o primeiro campo aparecer no Arquivo1. O Grep não fará isso. Em vez disso, tente:

$ awk 'FNR==NR{a[FNR]=$1;next} {for (k in a) if (a[k]==$1) print}' File1 File2
M01605:153:000000000-B55NK:1:1101:10003:14536 2:N:0:1 GTTTGCGCCGATGTA
M01605:153:000000000-B55NK:1:1101:10007:14573 2:N:0:1 GGGGATAAGCGTTGC
M01605:153:000000000-B55NK:1:1101:10007:14573 2:N:0:1 GGGGATAAGCGTTGC
M01605:153:000000000-B55NK:1:1101:10009:9160 2:N:0:1 CAGAAGAGGTAATGT
M01605:153:000000000-B55NK:1:1101:10009:9160 2:N:0:1 CAGAAGAGGTAATGT
M01605:153:000000000-B55NK:1:1101:10009:9160 2:N:0:1 CAGAAGAGGTAATGT
M01605:153:000000000-B55NK:1:1101:10010:14111 2:N:0:1 CTGCGTACTGATAGC
M01605:153:000000000-B55NK:1:1101:10010:19939 2:N:0:1 TCCGTGGTGCCGGCA
M01605:153:000000000-B55NK:1:1101:10011:22802 1:N:0:1 TGAGTTCGGATAAAG
M01605:153:000000000-B55NK:1:1101:10011:22802 1:N:0:1 TGAGTTCGGATAAAG

Como funciona

  • FNR==NR{a[FNR]=$1;next}

    Ao ler o primeiro arquivo, Arquivo1, armazene o primeiro campo, $1 , na matriz a sob a chave do número da linha, FNR .

  • for (k in a) if (a[k]==$1) print

    Durante a leitura do segundo arquivo, passe por cada elemento da matriz a e imprima a linha toda vez que uma correspondência for encontrada entre o primeiro campo do Arquivo2 e um valor da matriz a .

Alternativa mais eficiente

$ awk 'FNR==NR{a[$1]++;next} {for (i=1;i<=a[$1];i++) print}' File1 File2
M01605:153:000000000-B55NK:1:1101:10003:14536 2:N:0:1 GTTTGCGCCGATGTA
M01605:153:000000000-B55NK:1:1101:10007:14573 2:N:0:1 GGGGATAAGCGTTGC
M01605:153:000000000-B55NK:1:1101:10007:14573 2:N:0:1 GGGGATAAGCGTTGC
M01605:153:000000000-B55NK:1:1101:10009:9160 2:N:0:1 CAGAAGAGGTAATGT
M01605:153:000000000-B55NK:1:1101:10009:9160 2:N:0:1 CAGAAGAGGTAATGT
M01605:153:000000000-B55NK:1:1101:10009:9160 2:N:0:1 CAGAAGAGGTAATGT
M01605:153:000000000-B55NK:1:1101:10010:14111 2:N:0:1 CTGCGTACTGATAGC
M01605:153:000000000-B55NK:1:1101:10010:19939 2:N:0:1 TCCGTGGTGCCGGCA
M01605:153:000000000-B55NK:1:1101:10011:22802 1:N:0:1 TGAGTTCGGATAAAG
M01605:153:000000000-B55NK:1:1101:10011:22802 1:N:0:1 TGAGTTCGGATAAAG
    
por 14.09.2017 / 23:13
0

Supondo que ambos os arquivos são classificados da mesma maneira no primeiro campo:

$ join -o1.1,1.2,1.3 file2 file1
M01605:153:000000000-B55NK:1:1101:10003:14536 2:N:0:1 GTTTGCGCCGATGTA
M01605:153:000000000-B55NK:1:1101:10007:14573 2:N:0:1 GGGGATAAGCGTTGC
M01605:153:000000000-B55NK:1:1101:10007:14573 2:N:0:1 GGGGATAAGCGTTGC
M01605:153:000000000-B55NK:1:1101:10009:9160 2:N:0:1 CAGAAGAGGTAATGT
M01605:153:000000000-B55NK:1:1101:10009:9160 2:N:0:1 CAGAAGAGGTAATGT
M01605:153:000000000-B55NK:1:1101:10009:9160 2:N:0:1 CAGAAGAGGTAATGT
M01605:153:000000000-B55NK:1:1101:10010:14111 2:N:0:1 CTGCGTACTGATAGC
M01605:153:000000000-B55NK:1:1101:10010:19939 2:N:0:1 TCCGTGGTGCCGGCA
M01605:153:000000000-B55NK:1:1101:10011:22802 1:N:0:1 TGAGTTCGGATAAAG
M01605:153:000000000-B55NK:1:1101:10011:22802 1:N:0:1 TGAGTTCGGATAAAG

Isso executará uma operação de junção relacional usando o primeiro campo como a chave. Os campos que são enviados são especificados com o sinalizador -o como os três primeiros campos do primeiro arquivo ( file2 ).

Estou percebendo que a última linha na saída é extra em comparação com o resultado esperado. Eu estou supondo que isso é um erro é a questão.

A classificação é importante. Você deve pré-classificar os arquivos:

$ sort -o file1 file1
$ sort -o file2 file2

... ou classifique os arquivos imediatamente ao chamar join (requer um shell que entenda a substituição do processo por <(...) , como bash ):

$ join -o1.1,1.2,1.3 <( sort file2 ) <( sort file1 )

Isso será lento se você precisar executar a junção várias vezes, especialmente se os dois arquivos forem grandes.

    
por 14.09.2017 / 23:25

Tags