Comparar archivos de texto usando Bash y AWK

Comparar archivos de texto usando Bash y AWK

Tengo dos archivos de texto y quiero comparar sus valores correspondientes según sus filas y columnas. Al comparar, me refiero a comprobar si los valores son iguales y hacer eco si los valores son iguales o no. Aquí están los archivos:

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

Aquí están las restricciones:

  • compare solo las filas que existen (es decir, dado que la fila 3 existe en el archivo 1.txt, pero no en el archivo 2.txt, no es necesaria ninguna comparación)
  • Debe usarAWK
  • Las filas pueden estar desordenadas en los archivos.
  • No hay matrices dobles ya que mi versión de AWK no lo admite

Estoy pensando en algo como esto:

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

¿Cómo se comparan los valores de dos archivos de texto diferentes? Avíseme si se necesita más explicación.

Todo lo que pido es una estructura general que use AWK. Ojalá pueda descubrir el resto.

Respuesta1

Éste genera las líneas del archivo 2 donde el nombre está en ambos archivos pero cualquiera de los valores difiere

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

Me di cuenta de que incluso una diferencia en los espacios en blanco daría resultados falsos. Podemos "normalizar" las líneas:

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

Respuesta2

Hay muchas maneras de hacerlo, aquí tienes una solución con 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

Explicación

  • FNR < 2 { next }: salta las dos primeras líneas
  • FNR == NR: solo es cierto cuando procesamos el primer archivo. Guardamos el valor de cada columna en una matriz asociativa a, con forma a[ROW][COLUMN].
  • ($1 in a): compruebe si la fila del archivo2 existía en el archivo1. Si es verdadero, recorremos todo el valor de su columna y lo comparamos con el valor en el archivo1.

Con una gawkversión anterior, puedes probar:

$ 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

Respuesta3

Pruebe esto dentro del bucle for interno:

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

Esta es una declaración condicional simple que podría ayudar, pero puede que necesite algunos ajustes adicionales al comparar dos archivos de texto diferentes...

información relacionada