Combinar archivos usando una columna común

8

Tengo dos archivos de los cuales quiero crear un tercero que contenga toda la información.

archivo 1:

a 111 
b 222 
c 333 
d 666 
e 777 

archivo 2:

111 x1  
222 x2
333 x3
444 x4 
555 x5 
666 x6 
777 x7 
888 x8

Me gustaría combinarlos de la siguiente manera:

111  x1  a
222  x2  b
333  x3  c
444  x4  0
555  x5  0
666  x6  d
777  x7  e
888  x8  0

Nota:

La segunda columna del archivo 1 es un subconjunto de la primera columna del archivo 2

gforce89
fuente

Respuestas:

7

El joincomando hace casi lo que necesita, si los archivos se ordenan como en sus muestras:

join -12 -a2 file1 file2 -o2.1,2.2,1.1

Solo necesita agregar los ceros a las líneas sin coincidencia. Puede usar el -einterruptor para eso:

join -12 -a2 file1 file2  -o2.1,2.2,1.1 -e0
choroba
fuente
si agrega el -e0no necesita perl :)
LilloX
@LilloX: Cierto, gracias. Lo intenté pero fallé (error tipográfico).
choroba
13

Usando join:

join -1 1 -2 2 -a1 -e0 -o'0,1.2,2.1' file2 file1

El comando de unión une las líneas de dos archivos que comparten un campo de datos común. En este caso: Únase al archivo2 y al archivo1 usando el campo 1 ( -1 1) del archivo2 y el campo 2 ( -2 2) del archivo1.

La salida será: "campo unido, campo 2 del archivo2, campo 1 del archivo1" ( -o'0,1.2,2.1'), si falta un campo, coloque 0 ( -e0)

Si uno de los dos archivos tiene más registros, agréguelos (en este caso, archivo2) ( -a1)

Consulte la página de manual del comando join

LilloX
fuente
Bueno. ¿Podría agregar un poco de explicación?
Lety
Claro, actualizado :)
LilloX
5

Un poco de awkmagia

awk 'FNR==NR{a[$2]=$1;next}{if(a[$1]==""){a[$1]=0}; \
    printf "%s%s%s%s%s\n",$1,FS,$2,FS,a[$1]}' \
    file1 file2

o

awk 'FNR==NR{a[$2]=$1;next}{if(a[$1]==""){a[$1]=0};
    print $1,$2,a[$1]}' file1 file2

Salida

111 x1 a
222 x2 b
333 x3 c
444 x4 0
555 x5 0
666 x6 d
777 x7 e
888 x8 0

Explicación

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

    Se ejecuta sobre file1( FNR==NR) y crea una estructura clave-valor. La clave es la segunda columna ( $2) de file1, el valor es la primera columna ( $1) defile1

  • {if(a[$1]==""){a[$1]=0};print $1,$2,a[$1]}

    Atropella file2y

    • if(a[$1]==""){a[$1]=0}

      Si la clave en la primera columna ( $1) file2no existe en file1, necesitamos un0

    • print $1,$2,a[$1]

      Imprima (usando print) la primera y la segunda columna de file2y el valor de la estructura clave-valor con la clave de la primera columna ( $1) defile2

      o

    • printf "%s%s%s%s%s\n",$1,FS,$2,FS,a[$1]}'

      Imprima (usando printf) la primera y la segunda columna de file2y el valor de la estructura clave-valor con la clave de la primera columna ( $1) de file2.

      • FS es el separador entre las columnas, tomado del archivo de entrada

      • "%s%s%s%s%s\n"

        es el formato para la salida

        • %s - Cuerda

        • \n - Nueva línea

AB
fuente
¿Podrías explicar el código?
gforce89
Claro, respuesta actualizada.
AB
1

Usando q :

$ q "select f2.c1, f2.c2, ifnull(f1.c1,0) from file_2.txt f2 LEFT JOIN file_1.txt f1 on f1.c2 = f2.c1 "
111 x1 a
222 x2 b
333 x3 c
444 x4 0
555 x5 0
666 x6 d
777 x7 e
888 x8 0

Puede ser más legible de esta manera a veces.

Vi.
fuente
1
Para cualquiera que se pregunte, qestá en el paquete python3-q-text-as-data(Python 3) y en el paquete python-q-text-as-data(Python 2).
kos
Gracias, pero ¿dónde puedo obtener este qpaquete? No parecen ser capaces de instalar, ya sea python-q-text-as-datao python3-q-text-as-data. "E: no se puede encontrar el paquete python3-q-text-as-data". Mi sistema ya ha instalado python, python2.7, python3, y python3.4.
Paddy Landau
Tal vez el paquete es demasiado nuevo y no está disponible en su versión de distribución. Puedes clonarlo Github: github.com/harelba/q
Vi.