Vergleichen von Textdateien mit Bash und AWK

Vergleichen von Textdateien mit Bash und AWK

Ich habe zwei Textdateien und möchte die entsprechenden Werte anhand ihrer Zeilen und Spalten vergleichen. Mit Vergleichen meine ich, dass ich prüfen möchte, ob die Werte gleich sind, und eine Rückmeldung geben möchte, ob die Werte gleich sind oder nicht. Hier sind die Dateien:

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

Hier sind die Einschränkungen:

  • Vergleichen Sie nur die vorhandenen Zeilen (das heißt, da Zeile3 in Datei1.txt vorhanden ist, aber nicht in Datei2.txt, ist kein Vergleich erforderlich).
  • Benutzen müssenAWK
  • Die Zeilen in den Dateien sind möglicherweise nicht in der richtigen Reihenfolge
  • Keine doppelten Arrays, da meine Version von AWK dies nicht unterstützt

Ich denke an so etwas:

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

Wie vergleicht man Werte aus zwei verschiedenen Textdateien? Lassen Sie mich wissen, wenn weitere Erklärungen erforderlich sind.

Ich bitte lediglich um eine allgemeine Struktur mit AWK. Den Rest kann ich hoffentlich herausfinden.

Antwort1

Dieser gibt die Zeilen aus Datei2 aus, deren Name in beiden Dateien vorkommt, aber einige der Werte unterschiedlich sind

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

Mir ist aufgefallen, dass selbst ein Unterschied in den Leerzeichen zu falschen Ergebnissen führt. Wir können die Zeilen „normalisieren“:

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

Antwort2

Es gibt viele Möglichkeiten, dies zu tun. Hier ist eine Lösung mit 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

Erläuterung

  • FNR < 2 { next }: die ersten beiden Zeilen überspringen
  • FNR == NR: gilt nur, wenn wir die erste Datei verarbeiten. Wir speichern jeden Spaltenwert in einem assoziativen Array amit der Form a[ROW][COLUMN].
  • ($1 in a): Überprüfen Sie, ob die Zeile in Datei2 in Datei1 vorhanden ist. Wenn dies zutrifft, durchlaufen wir alle Spaltenwerte und vergleichen sie mit dem Wert in Datei1.

Bei älteren gawkVersionen können Sie Folgendes versuchen:

$ 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

Antwort3

Probieren Sie dies in der inneren For-Schleife aus:

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

Dies ist eine einfache bedingte Anweisung, die hilfreich sein könnte, aber beim Vergleichen zweier verschiedener Textdateien sind möglicherweise noch einige Anpassungen erforderlich …

verwandte Informationen