awk para comparar dois arquivos, extrair, enviar para terceiro [fechado]

1

Eu escrevi um script em Python, mas não é rápido o suficiente para esse trabalho.  Estou a pensar que o processamento linha a linha funcionaria melhor.

Eu tenho dois arquivos com duas colunas e potencialmente centenas de milhões de linhas (bioinformática). Os dois arquivos (file1, file2) são semelhantes, delimitados por tabulação, com a primeira coluna contendo strings de letras e números e a segunda coluna contendo inteiros. Os cabeçalhos são name , count em cada arquivo.

Eu preciso produzir um arquivo delimitado por tabulações onde: a primeira entrada de cada linha é da coluna name , mas somente os nomes que estão em file1 e file2 , a segunda entrada é a count para esse name do arquivo 1; e a terceira entrada é o count para esse name de file2 , preservando os cabeçalhos.

Depois de muita leitura, aqui está minha tentativa:

awk '(NR == FNR) {
   n0[] = 0; 
   n1[] = 0; 
   next
 }     {
   if( in n0) {
     n2[] = 0
   }
 } END {
   for (i in n0) (j in n1) (k in n2) {
     print i,"\t",j,"\t",k
   } 
}' file1 file2

É claro que não sei realmente o que estou fazendo com a criação de matrizes (não sei se podem ser bidimensionais, então tentei usar três).

Se alguém pudesse corrigir o script do awk usando a mesma sintaxe de fluxo básica como acima, isso seria excelente e muito apreciado.

também, para convertê-lo em um arquivo .sh executável, o que deve ser feito?

dos elementos da primeira coluna dos dois arquivos (somente os elementos que estão presentes nos dois arquivos encontram a interseção de valores entre os dois arquivos na primeira coluna e, em seguida,

    
por Matt 28.03.2015 / 16:47

2 respostas

3

Você ficaria muito melhor se a sua entrada fosse classificada na primeira coluna, desde então você pode usar diretamente o join comando:

$ cat foo 
a   1
b   2
c   3
d   4
$ cat bar
b   1
d   4
e   5
n   2
$ join -t $'\t' <(sort foo) <(sort bar)                                                                                                            
b   2   1
d   4   4

Em qualquer caso, eu recomendaria a classificação - sem a classificação, você provavelmente está olhando para O(m*n) operações, mas com classificação, O(m*log(m) + n*log(n) + min(m,n)) operações - você deve economizar um pouco se otimizar seus métodos em vez do linguagem que você usa.

Com awk , você pode usar uma única matriz:

awk 'NR==FNR { n[] = ; next } ( in n) {print , n[], }' foo bar

Isso também deve ser razoavelmente rápido, se $i in n for.

    
por muru 28.03.2015 / 18:14
2

com bash :

Assumindo file1 :

abc123 123456
def456 789123
ghi789 456789

e file2 :

abc123 789123

Isso gerará file3 :

abc123 123456 789123
#!/bin/bash

while read line1; do
    var1=$(echo $line1 | tr '\t' '\n')
    while read line2; do
        var2=$(echo $line2 | tr '\t' '\n')
        if [ "${var1[0]}" == "${var2[0]}" ]; then
            printf "%s\t%s\t%s\n" "${var1[0]}" "${var1[1]}" "${var1[2]}"
        fi
    done < file2
done < file1
    
por kos 28.03.2015 / 17:49