Unindo dois arquivos correspondentes a duas colunas com discordâncias e em cada linha correspondente, substitua a segunda coluna do arquivo 1 para a 6ª coluna no arquivo 2

1

Estou lutando com essa tarefa:

Eu tenho dois arquivos: o arquivo1 se parece com:

102 13.342
103 7.456
105 6.453
107 3.567
108 4.210

file2 se parece com:

0 098 0 0 0 -9 x
0 099 0 0 0 -9 x
0 100 0 0 0 -9 x
0 101 0 0 0 -9 x
0 102 0 0 0 -9 x
0 103 0 0 0 -9 x
0 104 0 0 0 -9 x
0 105 0 0 0 -9 x
0 106 0 0 0 -9 x
0 106 0 0 0 -9 x
0 107 0 0 0 -9 x
0 108 0 0 0 -9 x

E eu quero um arquivo3 que pareça

 0 098 0 0 0 -9 x
 0 099 0 0 0 -9 x
 0 100 0 0 0 -9 x
 0 101 0 0 0 -9 x
 0 102 0 0 0 13.342 x
 0 103 0 0 0 7.456 x
 0 104 0 0 0 -9 x
 0 105 0 0 0 6.453 x

Basicamente, quero unir arquivo1 e arquivo2 combinando primeiro e segundo campos em arquivo1 e arquivo2 respectivamente, mantendo inconsistências e também substituindo o valor do sexto campo no arquivo2 pelo valor do segundo campo no arquivo1 em cada linha correspondente ...

Eu sei que esta tarefa está relacionada com o uso de: %código%. Mas não consigo descobrir como continuar ... Também considerando o awk

    
por Emilio Mármol Sánchez 07.07.2016 / 13:02

2 respostas

3

Quando há tantos campos envolvidos, eu prefiro awk :

$ awk 'NR==FNR{a[$1]=$2; next}{if($2 in a){$6=a[$2]}}1;' file1 file2 
0 098 0 0 0 -9 x
0 099 0 0 0 -9 x
0 100 0 0 0 -9 x
0 101 0 0 0 -9 x
0 102 0 0 0 13.342 x
0 103 0 0 0 7.456 x
0 104 0 0 0 -9 x
0 105 0 0 0 6.453 x
0 106 0 0 0 -9 x
0 106 0 0 0 -9 x
0 107 0 0 0 3.567 x
0 108 0 0 0 4.210 x

Explicação

  • NR==FNR{a[$1]=$2; next} : NR é o número da linha atual e FNR é o número da linha atual do arquivo atual. Ao processar mais de um arquivo, os dois serão iguais apenas enquanto o primeiro arquivo estiver sendo lido. a[$1]=$2 usa o st field as a key to an array whose value is the 2nd field. The próximo skips to the next line. So, this will save all values from arquivo1 into the array a '.

  • if($2 in a){$6=a[$2]} : agora estamos lendo o segundo arquivo. Se o segundo campo dessa linha estiver presente na matriz a , defina o 6º campo ( $6 ) como o que estava armazenado em a para o segundo campo.

  • 1; : esta é uma abreviação de "imprimir esta linha".

por 07.07.2016 / 13:53
2

Se os dois arquivos forem classificados por campo-chave (e o 6º campo geralmente -9 )

join -1 2 -a 1 -e '-9' -o 1.1 1.2 1.3 1.4 1.5 2.2 1.7 file2 file1

faça o trabalho (obrigado a steeldriver para correção)
Mas mais correto pode ser com a formatação do sed :

join -1 2 -a 1 2 1 -o 1.1,1.2,1.3,1.4,1.5,1.6,2.2,1.7 |
sed 's/ \S*\( \S\+\)//3'

Se preferir awk e tenha certeza de que existem todas as chaves de file1 in file2

awk '{
    a=0
    do {
        if (a)
           print a
        getline a <"file2"
        split(a,A)
        }
    while($1 != A[2])
    i=0
    A[6]=$2
    for(i in A)
        printf("%s ",A[i++])
    print ""
    }' file1
    
por 07.07.2016 / 13:17