Comparando arquivos no unix em coluna

4

Eu quero comparar dois arquivos com o mesmo número de linhas e colunas com registros na mesma ordem. Só quero destacar as diferenças nos valores da coluna, se houver.

file A :

1,kolkata,19,ab

2,delhi,89,cd

3,bangalore,56,ef

file B :

1,kolkata,21,ab

2,mumbai,89,gh

3,bangalore,11,kl

Considerando a coluna 1 como chave primária, temos diferenças em outras colunas. Quero destacar essas diferenças.

O formato de saída pode ser (não tenho certeza):

record_number,  columns_with_diff
1               3

2               2,4

3               3,4

Pode diff ou comm resolver o meu problema? Se sim, qual seria o comando exato?

    
por user2910372 24.06.2014 / 14:53

2 respostas

3

Isso seria isso. Apenas algum problema de estilo com a vírgula extra no final de cada linha.

awk '
     BEGIN{ FS=","; ORS="" }

     { 
       # read line from secondary file
       getline aux < "file2"
       split(aux,f2,",")

       # print current line number
       print NR" "

       # process each field in current line
       for(i=1; i<=NF; i++) {
         if ($i!=f2[i]) {
           print i","
         }
       }
       print "\n"
     }
' file1

A saída:

1 3,
2 2,4,
3 3,4,
    
por 24.06.2014 / 15:27
1

Você pode fazer isso mais facilmente com perl :

$ perl -F',' -anle '
    BEGIN{
        print "record_number,  columns_with_diff";
        $" = ",";
    }
    if (!defined($h{$.})) {
        @{$h{$.}}{0..$#F} = @F[0..$#F];
    } else {
        @diff =  grep { $h{$.}{$_} ne $F[$_] } 0..$#F;
        print "$.\t\t@{[map {$_+1} @diff]}";
    } 
    close ARGV if eof;
' file1 file2
record_number,  columns_with_diff
1       3
2       2,4
3       3,4

Você deve remover linhas em branco na sua entrada para este trabalho.

Explicação

  • No bloco BEGIN , basta imprimir o cabeçalho da saída e, em seguida, definir o separador da lista como ,

  • @{$h{$.}}{0..$#F} = @F[0..$#F] : criamos um hash de hashes com as chaves do primeiro hash que são o número da linha, cada sub hashes tem as chaves index do campo menos 1 e os valores são valores coresspond com esses campos.

Aqui, usamos uma fatia de hash para atribuir rapidamente valores a hash de hashes.

se você usar Data::Dumper para imprimir o hash de hashes %h , poderá ver algo assim:

VAR1 = {
          '2' => {
                   '2' => '89',
                   '0' => '2',
                   '1' => 'delhi',
                   '3' => 'cd'
                 },
          '3' => {
                   '1' => 'bangalore',
                   '3' => 'ef',
                   '0' => '3',
                   '2' => '56'
                 },
          '1' => {
                   '3' => 'ab',
                   '1' => 'kolkata',
                   '0' => '1',
                   '2' => '19'
                 }
        };
  • Se criamos %h ( if (!defined($h{$.})) ) - significando que terminamos o processamento file1 - apenas comparamos cada campo da linha atual com o valor do coresspond em %h , armazenando todo o índice que é diferente em array @diff . map {$_+1} @diff restaura o número da coluna, porque o índice da matriz começa em 0, o número da coluna começa em 1.

  • close ARGV if eof restore $. counter.

por 24.06.2014 / 19:14

Tags