comparação de arquivos bash linha por linha com string selecionada

1

digamos que eu tenha dois arquivos a.txt, b.txt

a.txt

87621   3bde   NDF
87621   2dfg   NDF
87621   cdef   NDF
87621   abcd   NDF

b.txt

93291   abcd   NDF
93291   2dfg   NDF
93291   adbf   NDF
93291   gdrg   NDF

Meu script deve criar um arquivo, correspondendo a coluna 2 de ambos os arquivos e crie um arquivo com string correspondente no novo arquivo c.txt como abaixo

c.txt

2dfg
abcd

Eu tentei várias opções, mas não consegui, você pode ajudar!

    
por user261334 23.03.2014 / 21:47

3 respostas

0
comm -12 <(awk '{print }' a.txt | sort) <(awk '{print }' b.txt | sort) > c.txt

Explicação

  • <(...) é uma substituição de processo . Ou seja, a saída dos comandos dentro do (...) é substituída e usada como as duas entradas para comm .
  • awk '{print }' a.txt imprime apenas o segundo campo de cada linha.
  • sort ordena a saída pronta para entrada em comm .
  • comm compara dois arquivos classificados. As bandeiras -12 suprimem as linhas exclusivas de cada arquivo, imprimindo apenas as linhas comuns (consulte man comm para obter mais detalhes).
por Sparhawk 24.03.2014 / 01:14
1

Isto lê todas as linhas em a.txt e mantém o controle de todos os seus valores da coluna 2. Em seguida, ele lê b.txt e imprime todos os valores repetidos da coluna 2:

$ awk 'NR==FNR {seen[]=1; next} seen[]==1 {seen[]++; print }' a.txt b.txt
abcd
2dfg

O comando awk pode ser dividido em duas partes. A primeira parte é:

NR==FNR {seen[]=1; next}

awk primeiro testa se o número total de registros (linhas) processados, NR , é o mesmo que o número de registros processados nesse arquivo, FNR . Isso é verdade apenas para o primeiro arquivo processado, que é a.txt nesse caso. Assim, para cada linha em a.txt , a matriz associativa seen com uma chave configurada para o valor da segunda coluna, , é configurada para um valor de 1 . Isso será usado para indicar que esse valor da coluna 2 foi "visto" em a.txt . O comando a seguir é next , que diz awk para pular o restante dos comandos e ir buscar o próximo registro.

A segunda parte é:

seen[]==1 {seen[]++; print }

Por causa do comando next na primeira parte acima, essa parte é executada apenas pelo arquivo b.txt . Esta parte começa com um teste: ele verifica se o valor da coluna-2, , para este registro foi visto antes. Se foi visto antes uma vez, então os comandos entre chaves são executados. O primeiro comando entre chaves, seen[]++ incrementa o valor de seen para que nunca mais processemos esse valor da coluna-2. (Consequentemente, os valores de repetição da coluna-2 são ignorados.) O segundo comando simplesmente imprime o valor da coluna-2 que havia sido visto antes em a.txt .

Se pudermos confiar que não há valores repetidos para a coluna 2, é possível um script mais simples:

$ awk '{print }' a.txt b.txt | sort | uniq -d
2dfg
abcd
    
por John1024 24.03.2014 / 01:02
0

O seguinte perl one-liner fará o trabalho:

perl -lane 'BEGIN{%h}$h{$ARGV."\n".$F[1]}++;END{foreach(keys(%h)){s/.*\n//;$f{$_}++};for(keys(%f)){print if$f{$_}>1}}' a.txt b.txt > c.txt
    
por Sylvain Pineau 24.03.2014 / 00:28