Como mesclar valores de dois arquivos de texto diferentes?

2

Tenho os seguintes dados definidos em arquivos de texto:

file1.txt

a1:b1
a2:b2
a3:b3
a4:b4
a5:b5

file2.txt

b2:c1
b4:c2
b5:c3

Como mesclar esses valores para criar um arquivo de saída assim:

output.txt

a2:c1
a4:c2
a5:c3
    
por summertime-sadness 30.07.2015 / 19:37

2 respostas

5

Como seus arquivos parecem conter dados classificados, você deve poder usar o comando join , por exemplo,

join -12 -21 -t: -o1.1,2.2 file1.txt file2.txt > output.txt

Então

cat output.txt
a2:c1
a4:c2
a5:c3

Veja man join para detalhes das opções.

Se os arquivos forem não pré-classificados, você poderá classificá-los primeiro usando a substituição de processos. Observe, entretanto, que a classificação deve estar no campo no qual você deseja ingressar nos arquivos , por exemplo.

join -12 -21 -t: -o1.1,2.2 <(sort -t: -k2,2 file1.txt) <(sort -k1,1 file2.txt)
androgynous:hu2nt
gra7vel:fi6nal
cosm4etic:citizen

O resultado também estará em ordem de classificação: se você não quiser isso, há uma maneira bastante padrão de fazer esse tipo de coisa em awk usando uma matriz, por exemplo.

awk -F: 'NR==FNR {a[]=; next;} ( in a) {print a[]":";}' file1.txt file2.txt
    
por steeldriver 30.07.2015 / 19:42
5

Aqui está uma abordagem awk :

awk -F: '(NR==FNR){a[]=; next}( in a){print a[]":"};' file1 file2 > out

Explicação

  • awk -F: Run awk , definindo o separador de campo como : . Isto irá ler cada linha de entrada e dividir em : . Portanto, para a primeira linha de file1 , o primeiro campo ( ) é a1 e o segundo ( ) é b1 .
  • (NR==FNR){} : se NR for igual a FNR . NR é o número da linha de entrada atual e FNR é o número da linha do arquivo atual. Os dois serão iguais apenas enquanto o primeiro arquivo estiver sendo lido.
  • a[]=; next : salve o segundo campo como uma chave na matriz a cujo valor é o primeiro campo. Então, pule para a próxima linha.
  • ( in a){print a[]":"} : isso será executado apenas durante a leitura do segundo arquivo. Se o primeiro campo do segundo arquivo for uma matriz de chaves a , imprima o valor dessa chave (o segundo campo da linha correspondente de file1 ).

E um de Perl:

perl -F: -lanE '$k{$F[0]} ? say "$k{$F[0]}:$F[1]" : ($k{$F[1]}=$F[0]);' file1 file2 > out

Ou, se preferir:

perl -F: -lanE '$k{$F[0]} and say "$k{$F[0]}:$F[1]" or ($k{$F[1]}=$F[0]);' file1 file2 

Explicação

  • perl -F: -lanE : O -n significa "leia cada arquivo de entrada linha por linha e aplique o script dado por -E a cada um deles". -E , como -e , permite que você passe um script na linha de comando. A diferença é que -E habilita alguns recursos extras, como say . O -a ativa a divisão automática de cada linha de entrada no caractere fornecido por -F . Juntos, eles fazem perl agir muito como awk . Os campos são divididos em array @F e o primeiro campo é $F[0] , o segundo $F[1] etc. Finalmente, -l retira caracteres de nova linha ( \n ) do final de cada linha.
  • $k{$F[0]} ? foo : bar : Se a variável $k{$F[0]} estiver definida, do foo, else do bar.
  • ($k{$F[1]}=$F[0]) : isso acontece se $k{$F[0]} não estiver definido (é a "barra", acima). Ele salvará o segundo campo como uma chave no hash %k cujo valor é o primeiro campo.
  • say "$k{$F[0]}:$F[1]" : isso será executado se $k{$F[0]} for definido (o "foo" acima), portanto, se o primeiro campo da linha atual for um segundo campo em outra linha. Se fosse, imprimir ( say é como print , mas adiciona uma nova linha) o primeiro campo da corrente e o valor associado a ele no hash.
por terdon 31.07.2015 / 00:20