Une dois arquivos com diferentes números de colunas e linhas

2

Eu tenho dois arquivos. file_1.txt é assim:

R1     C1     C2     C3     C4     C5
R2     C1     C2     C3     C4     C5
R3     C1     C2     C3     C4     C5
R4     C1     C2     C3     C4     C5
R5     C1     C2     C3     C4     C5
R6     C1     C2     C3     C4     C5
R7     C1     C2     C3     C4     C5
R8     C1     C2     C3     C4     C5
R9     C1     C2     C3     C4     C5
R10    C1     C2     C3     C4     C5

arquivo_2.txt se parece com isto:

R4 C4 C5
R6 C4 C5
R7 C4 C5
R9 C4 C5

Eu gostaria de substituir os valores C4 e C5 em file_1.txt por aqueles que correspondem a eles de file_2.txt, mantendo os valores C1, C2 e C3 em file_1.txt inalterados.

O file_3.txt resultante deve ficar assim:

R1     C1     C2     C3     C4     C5
R2     C1     C2     C3     C4     C5
R3     C1     C2     C3     C4     C5
R4     C1     C2     C3     C4_new C5_new
R5     C1     C2     C3     C4     C5
R6     C1     C2     C3     C4_new C5_new
R7     C1     C2     C3     C4_new C5_new
R8     C1     C2     C3     C4     C5
R9     C1     C2     C3     C4_new C5_new
R10    C1     C2     C3     C4     C5

Todos os valores são números. As primeiras colunas em file_1.txt e file_2.txt são campos-chave e são classificadas em ordem numérica crescente.

Isso é algo que você pode fazer sozinho?

    
por Dave 23.11.2013 / 02:53

2 respostas

5

Esse problema faz com que uma aplicação típica de

awk 'NR == FNR{a1[$1]=$2; a2[$1]=$3; next};
    $1 in a1{$5=a1[$1]; $6=a2[$1]};{print}' file_2.txt file_1.txt     

Você pode ter que definir o separador de campo de saída explicitamente como guia, nesse caso

awk -v OFS='\t' 'NR == FNR{a1[$1]=$2; a2[$1]=$3; next};
    $1 in a1{$5=a1[$1]; $6=a2[$1]};{print}' file_2.txt file_1.txt 
    
por 23.11.2013 / 03:03
2

Isso não resolve o seu problema, mas mostra por que join pode soar como deveria funcionar nessa situação particular, mas não funciona. Passei um bom tempo tentando forçar o join a trabalhar em um problema semelhante ao seu neste site, intitulado: dois arquivos com identificador exclusivo .

1ª abordagem

Uma abordagem para uma solução para seu problema usando join seria algo assim:

$ join -a1 -1 1 -2 1 -o 1.1 1.2 1.3 1.4 2.2 2.3 <(sort file_1.txt) <(sort file_2.txt)
R10 C1 C2 C3  
R1 C1 C2 C3  
R2 C1 C2 C3  
R3 C1 C2 C3  
R4 C1 C2 C3 C4_new C5_new
R5 C1 C2 C3  
R6 C1 C2 C3 C4_new C5_new
R7 C1 C2 C3 C4_new C5_new
R8 C1 C2 C3  
R9 C1 C2 C3 C4_new C5_new

Como você pode ver, join precisa colocar seus arquivos em um formato ordenado, portanto, para iniciantes, se a ordem original de seus arquivos for importante, essa opção pode causar problemas.

Além disso, não é possível dizer a join para imprimir condicionalmente o valor de uma coluna de um dos arquivos ou o outro com base em seu valor ou na presença de um valor ou na falta de um valor.

segunda abordagem

Outra abordagem com join pode ser esta:

$ join -a1 -1 1 -2 1  <(sort file_1.txt) <(sort file_2.txt)
R10 C1 C2 C3 C4 C5
R1 C1 C2 C3 C4 C5
R2 C1 C2 C3 C4 C5
R3 C1 C2 C3 C4 C5
R4 C1 C2 C3 C4 C5 C4_new C5_new
R5 C1 C2 C3 C4 C5
R6 C1 C2 C3 C4 C5 C4_new C5_new
R7 C1 C2 C3 C4 C5 C4_new C5_new
R8 C1 C2 C3 C4 C5
R9 C1 C2 C3 C4 C5 C4_new C5_new

Novamente, está perto do que você quer, mas não permite que você use qualquer lógica condicional para imprimir uma coluna de um arquivo ou outro.

3ª abordagem

Este funciona, mas nós tivemos que quebrar e obter alguma ajuda externa de awk para omitir as colunas à direita que são deslocadas quando suas contrapartes existem em file_2.txt .

$ join -a1 -1 1 -2 1 -o 1.1 1.2 1.3 1.4 2.2 2.3 1.5 1.6 1.7 <(sort file_1.txt) <(sort file_2.txt) | awk '{$7=$8=""}1'
R10 C1 C2 C3 C4 C5  
R1 C1 C2 C3 C4 C5  
R2 C1 C2 C3 C4 C5  
R3 C1 C2 C3 C4 C5  
R4 C1 C2 C3 C4_new C5_new  
R5 C1 C2 C3 C4 C5  
R6 C1 C2 C3 C4_new C5_new  
R7 C1 C2 C3 C4_new C5_new  
R8 C1 C2 C3 C4 C5  
R9 C1 C2 C3 C4_new C5_new  

Use apenas entrar?

O Join tem um nicho muito restrito, onde pode ser uma ferramenta útil. Para um tipo de problema de substituição, com o qual você está mais alinhado, uma ferramenta como awk , perl ou sed seria mais adequada.

    
por 23.11.2013 / 05:08