Сравнение текстовых файлов с помощью Bash и AWK

Сравнение текстовых файлов с помощью Bash и AWK

У меня есть два текстовых файла, и я хочу сравнить их соответствующие значения по строкам и столбцам. Под сравнением я подразумеваю проверку, равны ли значения, и вывод, одинаковы ли значения или нет. Вот файлы:

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

Вот ограничения:

  • сравнивать только существующие строки (то есть, поскольку строка row3 существует в file1.txt, но не существует в file2.txt, сравнение не требуется)
  • Необходимо использоватьАВК
  • Строки в файлах могут быть расположены не по порядку.
  • Никаких двойных массивов, так как моя версия AWK их не поддерживает.

Я думаю о чем-то вроде этого:

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

Как сравнить значения двух разных текстовых файлов? Дайте мне знать, если нужны дополнительные объяснения.

Все, что я прошу, это общая структура с использованием AWK. Надеюсь, я смогу разобраться с остальным.

решение1

Этот выводит строки из файла file2, где имя есть в обоих файлах, но какие-либо значения различаются.

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

Я понял, что даже разница в пробелах даст ложные результаты. Мы можем «нормализовать» строки:

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

решение2

Есть много способов сделать это, вот решение 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

Объяснение

  • FNR < 2 { next }: пропустить первые две строки
  • FNR == NR: верно только при обработке первого файла. Мы сохраняем каждое значение столбца в ассоциативном массиве aс формой a[ROW][COLUMN].
  • ($1 in a): проверка, существует ли строка в file2 в file1. Если true, мы перебираем все значения столбцов, сравниваем со значением в file1.

В более старой gawkверсии вы можете попробовать:

$ 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

решение3

Попробуйте это внутри внутреннего цикла for:

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

Это простой условный оператор, который может помочь, но его, возможно, придется немного доработать, чтобы сравнить два разных текстовых файла...

Связанный контент