使用 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

以下是限制条件:

  • 仅比较存在的行(即,由于 file1.txt 中存在 row3,但 file2.txt 中不存在,因此不需要比较)
  • 必须使用AWK
  • 文件中的行可能没有顺序
  • 没有双数组,因为我的 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 内部 for 循环中尝试一下:

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

这是一个简单的条件语句,可能会有所帮助,但可能需要通过比较两个不同的文本文件进行一些额外的调整......

相关内容