Join: Dois arquivos - mas acrescente apenas as duas últimas colunas

5

Dados os arquivos:

1.txt

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

2.txt

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

OUTPUT.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 

Eu usei este como referência.

Eu tentei usar o seguinte:

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 produz:

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

Alguma ajuda?

    
por Sten Kin 27.09.2013 / 20:47

3 respostas

8

Eu não acho que você pode fazer isso com join sozinho. Você poderia fazer:

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 um loop de leitura de linha por linha como em sed / awk
  • -a , -F, : como o awk, divida as linhas em campos (na matriz @F ).
  • -l : funciona no conteúdo das linhas (funciona como awk , em que a entrada é dividida em RS ( $/ ) (mas RS não incluído em $0 ) e ORS ( $\ ) é anexado antes da impressão).
  • -e ... : perl [e] xpression para avaliar para cada linha.
  • Em seguida, lê-se quase como inglês: os campos 1 a 2 são definidos para os campos 5 a 6, se o campo 1 (o segundo campo como índices começa em 0) for "MISSING". Em seguida, defina o conteúdo do registro atual ($ _ é como $ 0 no awk) para os campos 0 a 4 e 7 a 8.

Na verdade, escrever o mesmo em awk não é mais complicado:

awk -F, -vOFS=, '$2 == "MISSING"{$2=$6;$3=$7}
                 {print $1,$2,$3,$4,$5,$8,$9}'
    
por 27.09.2013 / 22:04
4

usando apenas o 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  
    
por 27.09.2013 / 23:13
0

Parece que você deseja participar dos três primeiros campos. Em seguida, você deve alterar os dois primeiros delimitadores, join no novo primeiro campo e, em seguida, restaurar os 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'

retorna

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
    
por 08.08.2015 / 12:40