AWK - letzte Spalte zusammen mit leerem Wert drucken

AWK - letzte Spalte zusammen mit leerem Wert drucken

Wir können die letzte Spalte jeder Zeile in einer Datei ausdrucken, $NFwenn wir die letzte Spaltennummer nicht kennen.

Ich habe jedoch ein Problem, da die letzte Spalte einen leeren Wert aufweist.

Zum Beispiel,Parsing who-Befehl

$ who
root     tty1         2018-01-25 09:36
root     pts/0        2018-05-30 07:39 (192.168.1.134)
root     pts/1        2018-05-28 23:12 (192.168.1.134)
root     pts/2        2018-06-01 10:01 (192.168.1.188)

Ergebnis erhalten:

$ who | awk '{print $NF}'
09:36
(192.168.1.134)
(192.168.1.134)
(192.168.1.188)

erwartetes Ergebnis

(192.168.1.134)
(192.168.1.134)
(192.168.1.188)

Teilen Sie mir die Möglichkeiten mit, das erwartete Ergebnis in einem Einzeiler zu erzielen.

BEARBEITEN 1:Das obige Szenario ist nur ein Beispiel. Ich möchte das Trennzeichen nicht ändern, um das Ergebnis zu erzielen.

BEARBEITEN 2:nichts (eine leere Ausgabezeile) aus den Zeilen, die weniger Felder haben als das Maximum

Antwort1

Um nur die letzte Spalte mit den Zeilen auszugeben, die die maximale Spaltenanzahl aufweisen, können Sie Folgendes tun:

who | awk '
  NF > max  {max = NF; output = ""}
  NF == max {output = output $NF ORS}
  END       {printf "%s", output}'

So geben Sie für jede Eingabezeile eine Zeile aus, die jedoch für Zeilen, die nicht die maximale Spaltenanzahl aufweisen, leer bleibt:

who | awk '
  NF > max {max = NF}
  {n[NR] = NF}
  NF == max {last[NR] = $NF}
  END {for (i = 1; i <= NR; i++) print n[i] == max ? last[i] : ""}'

Antwort2

Wenn Sie nur das letzte Feld aus den Zeilen mit den meisten Feldern benötigen, müssen Sie die Daten zweimal durchlesen: einmal, um die höchste Anzahl von Feldern zu ermitteln, und ein weiteres Mal, um die Felder auszudrucken. Nur einmal zu lesen reicht nicht aus: Jede Zeile könnte mehr Felder als die vorherigen haben, und es gibt keine Möglichkeit, das herauszufinden.

Mit awk(beachten Sie, dass der Dateiname zweimal angegeben ist):

awk -vfields=0 'FNR==NR {if (NF > fields) fields=NF; next} 
     NF >= fields { print $NF } NF < fields {print ""}' file file

Wenn fileenthält

foo bar
one two three four
1 2 3
a b c d

Dadurch wird das vierte Feld gedruckt, oder es wird für Zeilen, die es nicht enthalten, leer gelassen:

vier

D

Das funktioniert natürlich nicht mit einer Pipe, da musst du eine temporäre Datei verwenden.

Eine alternative Lösung könnte darin bestehen, die zu druckenden Felder zwischenzuspeichern, bis eine Zeile mit weiteren Feldern erscheint, wie inStéphanes Antwort.

Antwort3

Überprüfen Sie, ob das 5. Feld übereinstimmt \(.*\), und drucken Sie es aus, wenn dies der Fall ist.

who | awk '$5 ~ /\(.*\)/{print $5}'

Wenn Sie nur an ipAdressen interessiert sind, ändern Sie den regulären Ausdruck:

who |  awk '$5 ~ /\((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\)/{print $5}'

Antwort4

Wenn Sie nur die letzte Spalte erhalten möchten, wenn diese Spalte verfügbar ist, nutzen Sie die Tatsache, dass Zeilen, die Sienichtmöchte nur vier Spalten haben:

who | awk 'NF > 4 { print $NF }'

oder, um ähnliche Daten zu erhalten,

w -hi | awk '{ print $3 }'

verwandte Informationen