Unirse: dos archivos, pero solo agregue las dos últimas columnas

Unirse: dos archivos, pero solo agregue las dos últimas columnas

Dados los archivos:

1.texto

1, abc, 123, 456, 789
2, lmn, 123, 456, 789
3, pqr, 123, 456, 789

2.texto

1, abc, 123, 000, 000
3, lmn, 123, 000, 000
9, opq, 123, 000, 000  

SALIDA.txt

ID, NAME, X,    1A,    1B,  2A,   2B   
1, abc, 123, 456, 789, 000, 000
2, lmn, 123, 456, 789, MISSING, MISSING
3, pqr, 123, 456, 789, 000, 000
9, opq, 123, MISSING, MISSING, 000, 000 

he usadoestepara referencia.

Intenté usar lo siguiente:

join -t , -a1 -a2 -1 1 -2 1 -o 0 -o 1.2 -o 1.3 -o 1.4 -o 1.5 -o 2.4 -o 2.5 -e "MISSING" 1.txt 2.txt

Que produce:

1, abc, 123, 456, 789, 000, 000
2, lmn, 123, 456, 789,MISSING,MISSING
3, pqr, 123, 456, 789, 000, 000
9,MISSING,MISSING,MISSING,MISSING, 000, 000

¿Alguna ayuda?

Respuesta1

No creo que puedas hacerlo joinsolo. Podrías hacerlo:

join -t, -a1 -a2 -o0,1.2,1.3,1.4,1.5,2.2,2.3,2.4,2.5 -e MISSING 1.txt 2.txt |
  perl -F, -lape '@F[1..2]=@F[5..6] if $F[1] eq "MISSING";
                  $_=join",",@F[0..4],@F[7..8]'
  • -p: use un bucle de lectura línea por línea como en sed/awk
  • -a, -F,: como awk, divide las líneas en campos (en la @Fmatriz).
  • -l: funciona con el contenido de las líneas (funciona como awkcuando la entrada se divide en RS( $/) (pero RSno se incluye en $0) y ORS( $\) se agrega antes de imprimir).
  • -e ...: expresión perl [e]xpresión para evaluar para cada línea.
  • Luego se lee casi como en inglés: los campos 1 a 2 se establecen en los campos 5 a 6 si el campo 1 (el segundo campo ya que los índices comienzan en 0) está "FALTA". Luego establezca el contenido del registro actual ($_ es como $0 en awk) en los campos 0 a 4 y 7 a 8.

En realidad, escribir lo mismo awkno es más complicado:

awk -F, -vOFS=, '$2 == "MISSING"{$2=$6;$3=$7}
                 {print $1,$2,$3,$4,$5,$8,$9}'

Respuesta2

usando solo awk:

awk -F, -v OFS=, '
    BEGIN {m = " MISSING"}

    # process file1
    NR == FNR {lines[$1] = $0; next} 

    # process file2
    {
        added[$1] = $4 OFS $5
        if (!($1 in lines)) {
            $4 = m
            $5 = m
            lines[$1] = $0
        }
    } 

    # print the combined output
    END {
        for (id in lines) {
            if (!(id in added)) 
                added[id] = m OFS m
            print lines[id], added[id]
        }
    }
' 1.txt 2.txt | sort -n
1, abc, 123, 456, 789, 000, 000
2, lmn, 123, 456, 789, MISSING, MISSING
3, pqr, 123, 456, 789, 000, 000
9, opq, 123, MISSING, MISSING, 000, 000  

Respuesta3

Parece que quieres unirte a los primeros tres campos. Luego debe cambiar los dos primeros delimitadores joinen el nuevo primer campo y luego restaurar los delimitadores:

join -t, -j1 -a1 -a2 -o 0 1.2 1.3 2.2 2.3 -e " MISSING" \
<(sed 's/, /\x02/;s/, /\x02/' 1.txt) <(sed 's/, /\x02/;s/, /\x02/' 2.txt) \
| sed 's/\x02/, /g'

devoluciones

1, abc, 123, 456, 789, 000, 000
2, lmn, 123, 456, 789, MISSING, MISSING
3, pqr, 123, 456, 789, 000, 000
9, opq, 123, MISSING, MISSING, 000, 000

información relacionada