Compare dois arquivos

2

Eu tenho dois arquivos no UNIX. 1º arquivo é Entidade e Segundo Arquivo é Referências. 1º arquivo tem apenas uma coluna chamada ID da entidade e o segundo arquivo tem duas colunas ID da entidade | ID da pessoa.

Eu quero produzir um arquivo de saída no qual os IDs da entidade estão correspondendo em ambos os arquivos.

Arquivo de entidades

624197
624252
624264
624276
624280
624309
624317

Arquivo de referência

624252|624346
624264|1070122
624264|624346
624276|624588
624280|624346
624280|624582
624298|624588
624319|333008
624330|624588

Arquivo de saída

624252|624346
624264|1070122
624264|624346
624276|624588
624280|624346
624280|624582

Os arquivos de entidades têm registros 90K e o arquivo de referência tem registros 200K. Existe uma maneira eficiente de produzir o terceiro arquivo? Qualquer solução é apreciada.

    
por PRS 06.12.2011 / 22:43

4 respostas

2

Assumindo que seus arquivos são classificados:

join -j1 -t\| entity.txt reference.txt

Se eles não estiverem classificados, classifique-os:

sort entity.txt -o entity-sorted.txt
sort reference.txt -o reference-sorted.txt
join -j1 -t\| entity-sorted.txt reference-sorted.txt
    
por 06.12.2011 / 23:13
0

Você pode fazer isso com um one-liner bash / zsh. Supondo que seus dados estejam contidos em arquivos chamados entity e reference , apenas digite:

for i in $(cat entity); do grep ^$i reference; done

em um console.

Além disso, você pode redirecionar toda a saída para um arquivo output , como

for i in $(cat entity); do grep ^$i reference; done > output

    
por 06.12.2011 / 23:17
0

Uma solução usando Perl :

Conteúdo de entity.txt :

$ cat entity.txt
624197
624252
624264
624276
624280
624309
624317

Conteúdo do reference.txt :

$ cat reference.txt 
624252|624346
624264|1070122
624264|624346
624276|624588
624280|624346
624280|624582
624298|624588
624319|333008
624330|624588

Conteúdo do script Perl:

$ cat script.pl
use warnings;
use strict;

## Check arguments.
@ARGV == 2 or die qq[Usage: perl $0 <entity-file> <reference-file>\n];

## File in process.
my $process_file = 1;

## Hash to save entities.
my %entity;


while ( <> ) {
        ## Process file of entities. Remove leading and trailing spaces, and save the
        ## number to a hash.
        if ( $process_file == 1 ) {
                s/\A\s*//;
                s/\s*\z//;
                if ( defined $_ ) { $entity{ $_ } = 1 }
                next;
        }

        ## Process file of references. Get first field and search it in the hash.
        ## If found, print the line.
        my @f = split /\|/, $_, 2;
        if ( exists $entity{ $f[0] } ) {
                print;
        }

} continue {
        ## Increment number when end processing first file.
        if ( eof ) { ++$process_file }
}

Executando o script sem argumentos:

$ perl script.pl
Usage: perl script.pl <entity-file> <reference-file>

Executando o script com argumentos e resultado:

$ perl script.pl entity.txt reference.txt 
624252|624346
624264|1070122
624264|624346
624276|624588
624280|624346
624280|624582
    
por 06.12.2011 / 23:24
0

Hmm, talvez eu esteja perdendo alguma coisa? Por favor, corrija-me se estiver errado:

$ while read id;do grep $id reference ;done <identity 
624252|624346
624264|1070122
624264|624346
624276|624588
624280|624346
624280|624582

Analisando seus arquivos de origem, eles já foram classificados, mas minha solução deve funcionar independentemente de eles estarem classificados ou não, acredito.

E para enviar para outro arquivo:

$ while read id;do grep $id reference ;done < identity > newoutput.out
    
por 07.01.2012 / 08:17