Comparando arquivos de texto usando Bash e AWK

2

Eu tenho dois arquivos de texto e quero comparar seus valores correspondentes de acordo com suas linhas e colunas. Comparando, quero verificar se os valores são iguais e eco se os valores são iguais ou não. Aqui estão os arquivos:

file1.txt

Name  Col1  Col2  Col3  
-----------------------
row1  1     4     7        
row2  2     5     8         
row3  3     6     9   

file2.txt

Name  Col1  Col2  Col3  
-----------------------
row2  1     4     11        
row1  2     5     12

Aqui estão as restrições:

  • compare apenas as linhas existentes (ou seja, como a row3 existe no arquivo1.txt, mas não no arquivo2.txt, nenhuma comparação é necessária)
  • Deve usar AWK
  • As linhas podem estar fora de ordem nos arquivos
  • Não há matrizes duplas, pois a minha versão do AWK não é compatível

Estou pensando em algo assim:

awk 'NR>2 {next}
{
    for (i=2;i<NR;i++)              #For each row of file1.txt
    {     
        for(j=1;i<NF;j++)           #For each column of file1.txt
        {
             // Check if row and column of file1.txt is equal to row and column of file2.txt.
        } 
    }
}
' file1.txt file2.txt

Como você compara valores de dois arquivos de texto diferentes? Deixe-me saber se é necessária mais explicação.

Tudo o que estou pedindo é uma estrutura geral usando o AWK. Espero poder descobrir o resto.

    
por Alias 19.06.2014 / 16:23

3 respostas

3

Há muitas maneiras de fazer isso, aqui está uma solução com gawk 4.x :

$ awk '
    FNR < 2 { next }
    FNR == NR {
        for (i = 2; i <= NF; i++) {
            a[$1][i] = $i;
        }
        next;
    }
    ($1 in a) {
      for (i = 2; i <= NF; i++) {
          if (a[$1][i] == $i) {
              printf("%s->Col%d: Equal\n", $1, i-1);
          } else {
              printf("%s->Col%d: Not Equal\n", $1, i-1);
          }
       }
  }
' file1.txt file2.txt
row2->Col1: Not Equal
row2->Col2: Not Equal
row2->Col3: Not Equal
row1->Col1: Not Equal
row1->Col2: Not Equal
row1->Col3: Not Equal

Explicação

  • FNR < 2 { next } : pule as duas primeiras linhas
  • FNR == NR : true apenas quando processamos o primeiro arquivo. Nós salvamos cada valor de coluna no array associativo a , com o formulário a[ROW][COLUMN] .
  • ($1 in a) : verifique se a linha no arquivo2 existia no arquivo1. Se true, percorremos todo o valor da coluna, compare com o valor no arquivo1.

Com a versão gawk mais antiga, você pode tentar:

$ awk '
    FNR < 2 { next }
    FNR == NR {
        for (i = 2; i <= NF; i++) {
            a[i,$1] = $i;
            b[$1];
        }
        next;
    }
    ($1 in b) {
      for (i = 2; i <= NF; i++) {
          if (a[i,$1] == $i) {
              printf("%s->Col%d: Equal\n", $1, i-1);
          } else {
              printf("%s->Col%d: Not Equal\n", $1, i-1);
          }
       }
  }
' file1.txt file2.txt
    
por 19.06.2014 / 16:37
4

Este produz as linhas do arquivo2 onde o nome está nos dois arquivos, mas qualquer um dos valores é diferente

awk 'NR==FNR {f1[$1]=$0; next} $1 in f1 && $0 != f1[$1]' file1.txt file2.txt 
row2  1     4     11        
row1  2     5     12

Eu percebi que até mesmo uma diferença no espaço em branco dará resultados falsos. Podemos "normalizar" as linhas:

awk '
    NR==FNR  {$1=$1; f1[$1]=$0; next} 
    $1 in f1 {$1=$1; if ($0 != f1[$1]) print}
' file1.txt file2.txt 
row2 1 4 11
row1 2 5 12
    
por 19.06.2014 / 16:43
1

Teste isso dentro de loop interno:

awk ' {
      if(i == j)
           print "Same value";
      else
           print "Not the same";
       }'

Esta é uma instrução condicional simples que pode ajudar, mas pode precisar de alguns ajustes adicionais ao comparar dois arquivos de texto diferentes ...

    
por 19.06.2014 / 16:39