UNIX-Spalten einfügen und Nullen für alle fehlenden Werte einfügen

UNIX-Spalten einfügen und Nullen für alle fehlenden Werte einfügen

Ich möchte bestimmte Spalten aus zwei TXT-Dateien zusammenführen, die eine unterschiedliche Zeilenanzahl, aber die gleiche Spaltenanzahl enthalten (wie unten gezeigt):

  file1:
  xyz   desc1   12
  uvw   desc2   55
  pqr   desc3   12

  file2:
  xyz   desc1   56
  uvw   desc2   88


  Preferred output:
  xyz   desc1   12  56
  uvw   desc2   55  88
  pqr   desc3   12   0

Derzeit verwende ich den Paste-Befehl mit awk wie folgt:

  paste <(awk '{print $1}' file1) <(awk '{print $2}' file1) <(awk '{print $3}' file1) <(awk '{print $3}' file2) 

Dies scheint jedoch nur Spalten zusammenzuführen, die sich überlappen. Gibt es in awk eine Möglichkeit, Nullen einzufügen, anstatt die Zeile selbst wegzulassen?

Ich muss 100 Dateien so zusammenführen, dass meine Ausgabedatei 102 Spalten enthält.

Antwort1

Wenn die Spaltenreihenfolge wichtig ist, d. h. Zahlen aus derselben Datei in derselben Spalte bleiben sollen, müssen Sie beim Lesen der verschiedenen Dateien Auffüllungen hinzufügen. Hier ist eine Möglichkeit, die mit GNU awk funktioniert:

zusammenführen.awk

# Set k to be a shorthand for the key
{ k = $1 SUBSEP $2 }

# First element with this key, add zeros to align it with other rows
!(k in h) {
  for(i=1; i<=ARGIND-1; i++)
    h[k] = h[k] OFS 0 
}

# Remember the data element
{ h[k] = h[k] OFS $3 }

# Before moving to the next file, ensure that all rows are aligned
ENDFILE {
  for(k in h) {
    if(split(h[k], a) < ARGIND)
      h[k] = h[k] OFS 0
  }
}

# Print out the collected data
END {
  for(k in h) {
    split(k, a, SUBSEP)
    print a[1], a[2], h[k]
  }
}

Hier sind einige Testdateien: f1, f2, f3und f4:

$ tail -n+1 f[1-4]
==> f1 <==
xyz desc1 21
uvw desc2 22
pqr desc3 23

==> f2 <==
xyz desc1 56
uvw desc2 57

==> f3 <==
xyz desc1 87
uvw desc2 88

==> f4 <==
xyz desc1 11
uvw desc2 12
pqr desc3 13
stw desc1 14
arg desc2 15

Prüfung 1

awk -f merge.awk f[1-4] | column -t

Ausgabe:

pqr  desc3  23  0   0   13
uvw  desc2  22  57  88  12
stw  desc1  0   0   0   14
arg  desc2  0   0   0   15
xyz  desc1  21  56  87  11

Prüfung 2

awk -f merge.awk f2 f3 f4 f1 | column -t

Ausgabe:

pqr  desc3  0   0   13  23
uvw  desc2  57  88  12  22
stw  desc1  0   0   14  0
arg  desc2  0   0   15  0
xyz  desc1  56  87  11  21

Bearbeiten:

Wenn die Ausgabe tabulatorgetrennt sein soll, legen Sie den Ausgabefeldtrenner entsprechend fest:

awk -f merge.awk OFS='\t' f[1-4]

Antwort2

Versuche dies:

$ awk '
    FNR == NR { a[$1,$2] = $3; next }
    {
        print $0,(($1,$2) in a) ? a[$1,$2] : "0"
    }
' file2 file1
xyz   desc1   12 56
uvw   desc2   55 88
pqr   desc3   12 0

Antwort3

Das ist zwar etwas lang, funktioniert aber:

$ cat file1 file2 | awk '{a[$1FS$2]=a[$1FS$2]FS$3; b[$1FS$2]++} END {for (i in b) max=max<b[i]?b[i]:max; for (i in a) {printf "%s %s", i, a[i]; for (j=b[i]; j<max; j++) printf "%s0", FS  printf "%s", RS}}' 
pqr desc3  12 0
xyz desc1  12 56
uvw desc2  55 88

Der Awk-Block kann wie folgt formatiert werden:

awk '{a[$1FS$2]=a[$1FS$2]FS$3; b[$1FS$2]++}
      END {for (i in b) max=max<b[i]?b[i]:max
          for (i in a) {printf "%s%s%s", i, FS, a[i]
                        for (j=b[i]; j<max; j++) printf "%s0", FS
                        printf "%s", RS}
          }'

Die Idee besteht darin, alle Dateien auszudrucken und dann die wiederholten Werte im Array abzufangen a[$1 $2]. b[$1 $2]Enthält außerdem die Häufigkeit, mit der ein Paar ( $1, $2) vorkam.

Im END{}Block durchlaufen wir weiterhin die Werte und schließen mit so vielen Elementen ab, 0wie von der Anzahl der Elemente bis zur maximalen Anzahl der Elemente fehlen.

verwandte Informationen