Une dos archivos con columnas coincidentes

11

File1.txt

    id                            No
    gi|371443199|gb|JH556661.1| 7907290
    gi|371443198|gb|JH556662.1| 7573913
    gi|371443197|gb|JH556663.1| 7384412
    gi|371440577|gb|JH559283.1| 6931777

File2.txt

 id                              P       R       S
 gi|367088741|gb|AGAJ01056324.1| 5       5       0
 gi|371443198|gb|JH556662.1|     2       2       0
 gi|367090281|gb|AGAJ01054784.1| 4       4       0
 gi|371440577|gb|JH559283.1|     21      19      2

output.txt

 id                              P       R       S  NO
 gi|371443198|gb|JH556662.1|     2       2       0  7573913
 gi|371440577|gb|JH559283.1|     21      19      2  6931777

File1.txt tiene dos columnas y File2.txt tiene cuatro columnas. Quiero unir ambos archivos que tienen una identificación única (la matriz [1] debe coincidir en ambos archivos (file1.txt y file2.txt) y dar a la salida solo la identificación coincidente (ver output.txt).

He tratado join -v <(sort file1.txt) <(sort file2.txt). Cualquier ayuda con awk o unirse a los comandos solicitados.

Jack
fuente

Respuestas:

18

join Funciona genial:

$ join <(sort File1.txt) <(sort File2.txt) | column -t | tac
 id                           No       P   R   S
 gi|371443198|gb|JH556662.1|  7573913  2   2   0
 gi|371440577|gb|JH559283.1|  6931777  21  19  2

PD. ¿Importa el orden de las columnas de salida?

en caso afirmativo use:

$ join <(sort 1) <(sort 2) | tac | awk '{print $1,$3,$4,$5,$2}' | column -t
 id                           P   R   S  No
 gi|371443198|gb|JH556662.1|  2   2   0  7573913
 gi|371440577|gb|JH559283.1|  21  19  2  6931777
prisa
fuente
Funciona genial. el orden de las columnas no importa
jack
¿Cuál es la razón para incluir tac?
Michael Mrozek
Eso es porque sortcoloca la cadena del encabezado al final. En realidad es una solución sucia. Y en general, el encabezado del caso puede ir al centro de la salida. Sin embargo funciona aquí.
prisa el
10

Una forma de usar awk:

Contenido de script.awk:

## Process first file of arguments. Save 'id' as key and 'No' as value
## of a hash.
FNR == NR {
    if ( FNR == 1 ) { 
        header = $2
        next
    }   
    hash[ $1 ] = $2
    next
}

## Process second file of arguments. Print header in first line and for
## the rest check if first field is found in the hash.
FNR < NR {
    if ( $1 in hash || FNR == 1 ) { 
        printf "%s %s\n", $0, ( FNR == 1 ? header : hash[ $1 ] ) 
    }   
}

Ejecútalo como:

awk -f script.awk File1.txt File2.txt | column -t

Con el siguiente resultado:

id                           P   R   S  NO
gi|371443198|gb|JH556662.1|  2   2   0  7573913
gi|371440577|gb|JH559283.1|  21  19  2  6931777
Birei
fuente
+65535 para mantener el orden de línea original. :-)
zeekvfu
+65535 para mantener el orden de línea original. :-)
zeekvfu