使用 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";
       }'

這是一個簡單的條件語句,可能會有所幫助,但可能需要透過比較兩個不同的文字檔案進行一些額外的調整...

相關內容