Mesclando 2 arquivos e mantendo um duplicado

1

Eu quero criar um arquivo que contenha colunas de dois arquivos de entrada.

File1 é como:

11111111        abc12345   Y
22222222        xyz23456   Y

Arquivo2:

11111111       abc12345    
33333333       kbc34567

A saída deve ser como:

11111111        abc12345   Y
22222222        xyz23456   Y
33333333        kbc34567

Eu tentei o seguinte e consegui encontrar a duplicata, mas preciso da entrada duplicada do primeiro arquivo e de outros registros também e com a mesma formatação (mesma quantidade de espaço entre a 1ª, a 2ª e a 3ª coluna):

awk 'FNR==NR{a[$1$2]=$1$2;next} ($1$2 in a) {print a[$1$2],$3}' file2 file1
    
por Ayesha 25.01.2016 / 09:05

3 respostas

1

O espaço está sendo alterado porque você está imprimindo i) o 1º e o 2º campo concatenados e ii) o terceiro campo. Por padrão, awk usa um espaço como o separador do campo de saída ( OFS ), o que estraga seu espaçamento. Uma solução simples é salvar a própria linha ( $0 ) na matriz, em vez dos campos:

a[$1$2]=$0;

No entanto, o seu script não faz o que você quer de qualquer maneira. Ele só imprimirá linhas do arquivo1 que estavam presentes no arquivo2, portanto, qualquer coisa que esteja apenas no arquivo1 será ignorada. De acordo com a saída desejada, você deseja imprimir todas as linhas de ambos os arquivos e, se qualquer linha do arquivo2 tiver os mesmos dois primeiros campos como um no arquivo1, imprima apenas a linha correspondente do arquivo1. Você pode fazer isso em awk com:

awk 'FNR==NR{a[$1$2]=$0; print} !($1$2 in a) {print}' file1 file2 

Isso salvará cada linha de file1 na matriz e também a imprimirá. Então, quando file2 estiver sendo processado, ele imprimirá qualquer linha cujos primeiros dois campos não estejam em a .

Note que você também pode fazer isso usando sort :

$ sort -uk1,2 file1 file2 
11111111    abc12345    Y
22222222    xyz23456    Y
33333333    kbc34567

Você só precisa se certificar de que a quantidade de espaço em branco nos dois arquivos é a mesma (o que não é o caso do seu exemplo) ou fazer isso com:

$ sed  's/  */\t/g' file1 file2 | sort -uk1,2 
11111111    abc12345    Y
22222222    xyz23456    Y
33333333    kbc34567
    
por 25.01.2016 / 10:43
0

Dependendo do tamanho dos seus arquivos, esse pode não ser o método mais eficiente, mas acho que funcionará para o caso específico. Ele não exige que os arquivos estejam em uma ordem específica, mas exige que você sempre preferir o File1 ao File2:

#!/bin/bash
# Make a list of the unique identifiers in each of the files, changing the whitespace in between into a comma.
awk '{print $1 "," $2}' File1 File2| sort | uniq |
# Loop through all the unique identifiers we just found
while read l; do
    # Create a regular expression for each identifier to use as
    #  a search term, changing the comma into "any number of whitespaces"
    searchterm=$(echo $l | sed 's/,/\\s*/')
    # if this pattern exists in File1
    if $(grep -E "$searchterm" File1 >& /dev/null); then
        # print it out
        grep -E "$searchterm" File1
    else
        # otherwise, print it if it's in File2
        grep -E "$searchterm" File2
    fi
done 

Se você quiser o File3, você pode salvá-lo como um script e enviar a saída para lá

#copy to merge_uniq.sh
chmod +x merge_uniq.sh
merge_uniq.sh > File3
    
por 25.01.2016 / 10:44
0
awk 'BEGIN{i=0} {if (!($1$2  in a)) {a[$1$2]=$0; index_array[i] =$1$2; i++} } END{for (j=0; j<i; j++) print a[index_array[j]]}' 1 2

11111111        abc12345   Y

22222222        xyz23456   Y
33333333       kbc34567
    
por 25.01.2016 / 11:35