Mesclar 2 arquivos com base em todos os valores da primeira coluna do primeiro arquivo

5

Eu preciso mesclar abaixo de 2 arquivos:

  • file1 :

TABLES REF-IO HEAD-IO DIFF-IO
test 200 500 -300
exam 2 3 -1
final 2 1 1
mail 4 2 2
TOTAL 208 506 -298

  • file2 :

TABLES REF-SELECT HEAD-SELECT DIFF-SELECT
test 5 7 -2
game 3 3 0
exam 0 7 -7
final 12 6 6
TOTAL 20 23 -3

O arquivo mesclado

deve ser o seguinte:

TABLES REF-IO HEAD-IO DIFF-IO REF-SELECT HEAD-SELECT DIFF-SELECT
test 200 500 -300 5 7 -2
exam 2 3 -1 0 7 -7
final 2 1 1 12 6 6
mail 4 2 2 0 0 0
TOTAL 208 506 -298 20 23 -3

    
por ekassis 03.04.2014 / 12:07

4 respostas

5
awk '
    NR==FNR {vals[$1] = $2 " " $3 " " $4; next} 
    !($1 in vals) {vals[$1] = "0 0 0"} 
    {$(NF+1) = vals[$1]; print}
' file2 file1
TABLES REF-IO HEAD-IO DIFF-IO REF-SELECT HEAD-SELECT DIFF-SELECT
test 200 500 -300 5 7 -2
exam 2 3 -1 0 7 -7
final 2 1 1 12 6 6
mail 4 2 2 0 0 0
TOTAL 208 506 -298 20 23 -3
    
por 03.04.2014 / 12:43
1

Veja como fazer isso com join e preservar a ordem de linha, cabeçalhos, rodapés, etc ...

join -1 2 -2 1 -a 1 -e 0 -o 1.1,1.2,1.3,1.4,1.5,2.2,2.3,2.4 \
<(sort -k2,2 <(nl -ba -nrz file1)) <(sort -k1,1 file2) | \
sort -k1,1n | cut -d\  -f2-

resultado:

TABLES REF-IO HEAD-IO DIFF-IO REF-SELECT HEAD-SELECT DIFF-SELECT
test 200 500 -300 5 7 -2
exam 2 3 -1 0 7 -7
final 2 1 1 12 6 6
mail 4 2 2 0 0 0
TOTAL 208 506 -298 20 23 -3

Como funciona:

nl -ba -nrz file1 numera as linhas em file1 , a saída é então sort ed no 2º campo; file2 também é sort ed no 1º campo e os resultados são join ed no 2º campo da 1ª entrada e 1º campo da 2ª entrada, substituindo campos de entrada faltantes com 0 :

000003 exam 2 3 -1 0 7 -7
000004 final 2 1 1 12 6 6
000005 mail 4 2 2 0 0 0
000001 TABLES REF-IO HEAD-IO DIFF-IO REF-SELECT HEAD-SELECT DIFF-SELECT
000002 test 200 500 -300 5 7 -2
000006 TOTAL 208 506 -298 20 23 -3

isso é classificado no primeiro campo com sort -k1,1n para restaurar a ordem das linhas e, em seguida, cut -d\ -f2- remove os números das linhas. Você poderia ainda embelezar com column , por exemplo .... | column -t :

TABLES  REF-IO  HEAD-IO  DIFF-IO  REF-SELECT  HEAD-SELECT  DIFF-SELECT
test    200     500      -300     5           7            -2
exam    2       3        -1       0           7            -7
final   2       1        1        12          6            6
mail    4       2        2        0           0            0
TOTAL   208     506      -298     20          23           -3
    
por 14.07.2015 / 21:40
0

Este script deve funcionar:

touch resultFile
while read f; do
    header1=$(echo $f | awk '{print $1;}');
    values1=$(echo $f | awk -F "$header1 " '{print $NF;}');
    while read g; do
        header2=$(echo $g | awk '{print $1;}');
        values2=$(echo $g | awk -F "$header2 " '{print $NF;}');
        if [ $header1 = $header2 ]; then
            echo "$header1 $values1 $values2" >> resultFile
        fi
    done < file2
done < file1

Os cabeçalhos devem ser únicos, caso contrário, somente a última linha encontrada será mesclada.

PS: Eu considerei que o cabeçalho "mail" não deveria estar presente no resultado, pois não está presente em ambos os arquivos, como "game" (no seu exemplo "mail" está presente, mas não "game"). / p>     

por 03.04.2014 / 12:35
0

Caso você esteja se perguntando, é possível fazer isso com join , embora a ordem das linhas não seja preservada:

(
  join <(head -n1 file1) <(head -n1 file2)
  join -a 1 -e 0 -o '0 1.2 1.3 1.4 2.2 2.3 2.4' \
                    <(sed -n 2,5p file1 | sort) \
                    <(sed -n 2,5p file2 | sort)
  join <(tail -n1 file1) <(tail -n1 file2)
)

Saída:

TABLES REF-IO HEAD-IO DIFF-IO REF-SELECT HEAD-SELECT DIFF-SELECT
exam 2 3 -1 0 7 -7
final 2 1 1 12 6 6
mail 4 2 2 0 0 0
test 200 500 -300 5 7 -2
TOTAL 208 506 -298 20 23 -3
    
por 03.04.2014 / 15:31