Bash と AWK を使用してテキスト ファイルを比較する

Bash と AWK を使用してテキスト ファイルを比較する

2 つのテキスト ファイルがあり、行と列に応じて対応する値を比較したいと考えています。比較するというのは、値が等しいかどうかを確認し、値が同じかどうかを返すことを意味します。ファイルは次のとおりです。

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

制約は次のとおりです。

  • 存在する行のみを比較します (つまり、行 3 は file1.txt には存在しますが、file2.txt には存在しないため、比較は必要ありません)
  • 使用必須AWK
  • ファイル内の行の順序が間違っている可能性があります
  • 私のAWKのバージョンではサポートされていないため、double配列は使用できません。

私は次のようなことを考えています:

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

2 つの異なるテキスト ファイルの値をどのように比較しますか? さらに説明が必要な場合はお知らせください。

私が求めているのは、AWK を使用した一般的な構造だけです。残りは理解できればいいのですが。

答え1

これは、名前が両方のファイルに存在するが、値が異なるファイル2の行を出力します。

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 }: 最初の2行をスキップ
  • FNR == NR: 最初のファイルを処理するときのみ true です。各列の値をa、形式で連想配列に保存しますa[ROW][COLUMN]
  • ($1 in a): ファイル2 の行がファイル1 に存在するかどうかを確認します。存在する場合は、そのすべての列の値をループし、ファイル1 の値と比較します。

古い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";
       }'

これは役に立つかもしれない単純な条件文ですが、2 つの異なるテキスト ファイルを比較するには追加の調整が必要になる可能性があります...

関連情報