Encontre registros presentes no arquivo 1 também no arquivo 2 e no arquivo 3

1

Eu tenho três arquivos file1.txt , file2.txt , file3.txt e eles são do mesmo formato.

Eu quero selecionar registros de file1.txt que estão presentes em file2.txt e file3.txt com base nas colunas 2 e 3, respectivamente, no arquivo de saída out.txt . Você poderia por favor me avisar como fazer isso?

Além disso, preciso criar outro arquivo, out2.txt , com colunas adicionais (coluna 4 de file2.txt , coluna 5 de file3.txt ). Seria muito útil se você explicasse o comando tão bem quanto eu sou muito novo neste mundo unix.

Entrada de amostra:

file1.txt

1. abc 1 a f11 f13 f14 
2. abd 2 b f12 f14 f13  
3. abe 4 d f13 f16 f12 
4. acf 6 s f14 f15 f19

file2.txt

 1. abc 1 a f21 f23 f24 
 2. abd 1 b f21 f24 f23  
 3. abe 4 d f24 f26 f22 
 4. acf 6 s f23 f25 f29

file3.txt

 1. abc 1 a f31 f33 f34 
 2. abd 2 b f31 f34 f33  
 3. acf 5 s f33 f35 f39 
 4. abe 4 d f34 f36 f32

Saída desejada

out.txt

 1. abc 1 a f11 f13 f14 
 2. abe 4 d f13 f16 f12 

out2.txt

 1. abc 1 a f11 f13 f14 f21 f31
 2. abe 4 d f13 f16 f12 f24 f34
    
por Prradep 18.05.2015 / 16:15

3 respostas

2

Possível solução com awk (vou editar, se necessário, porque é um pouco incerto da sua pergunta quais são os requisitos exatos):

awk 'FILENAME == ARGV[1] {
    m[$2,$3] = 0; z[$2,$3] = $5;
    next; 
}
FILENAME == ARGV[2] {
    if (($2,$3) in m) {
        m[$2,$3] = 1;
        z[$2,$3] = $5 " " z[$2,$3];
    }
    next;
}
{
    if (($2,$3) in m && m[$2,$3] == 1) {
        print $0 >"out.txt";
        print $0 " " z[$2,$3] >"out2.txt";
    }
}' file3.txt file2.txt file1.txt

Nós lemos o terceiro arquivo, criamos dois arrays com as chaves nas colunas 2 e 3, o primeiro array preenchido com zeros, o segundo com o valor requerido para o arquivo out2.txt. Então nós lemos o segundo arquivo e nós checamos se a chave da coluna 2 e 3 existe no primeiro array, se sim nós mudamos o valor de zero para um e nós concatenamos o valor requerido no segundo array para o arquivo out2.txt. Finalmente lemos o primeiro arquivo, checamos a chave existente e imprimimos valores interessantes nos arquivos out.txt e out2.txt, então:

out.txt deve conter:

1. abc 1 a f11 f13 f14
3. abe 4 d f13 f16 f12

out2.txt deve conter:

1. abc 1 a f11 f13 f14 f21 f31
3. abe 4 d f13 f16 f12 f24 f34
    
por 18.05.2015 / 19:51
3

Você pode querer verificar este site sobre o diff3 com este programa você pode comparar 3 arquivos como exemplo de saída:

$ diff3 parent.txt your.txt mine.txt

 ==== 

1:1,2c Hello, 

This is parent file.

2:1,2c Hello, 

This is your file. 

3:1,2c Hello, 

This is my file.

Você pode usar

diff3 file1.txt file2.txt file3.txt > output.txt
    
por 18.05.2015 / 16:26
3

Para selecionar linhas compartilhadas em todos os arquivos, você pode usar grep ( out.txt )

grep -ho ' [0-9] [a-z] ' file3 | grep -Fof - file2 | grep -Ff - file1

selecione o campo operável (como variante cut -d' ' -f3,4 file3 ) e use-o para pesquisá-lo nos próximos file2 e file1 .

Como de costume para juntar 2 arquivos, use join command (surpresa!) ( out2.txt )

join -j 3 <(sort -k3,4 file1 | sed 's/ /+/3') \
          <(join -j 3 <(sort -k3,4 file2 | sed 's/ /+/3') \
                      <(sort -k3,4 file3 | sed 's/ /+/3') \
                      -o '1.4 2.4 1.3') \
          -o '1.1,1.2,1.3,1.4,1.5,2.1,2.2' | sed 's/+/ /'

então, para operar com os campos 3 e 4 juntos, temos que concatená-lo (por + sign, por exemplo). Como join funciona apenas com linhas ordenadas, por isso fazemos sort nos campos 3 e 4.
Em primeiro lugar, junte-se file2 e file3 , e o resultado será associado a file1 e remova + sign by sed

    
por 18.05.2015 / 18:42