Drucken Sie die vorletzte Spalte / das vorletzte Feld in awk

164

Ich möchte die vorletzte Spalte oder das vorletzte Feld in awk drucken. Die Anzahl der Felder ist variabel. Ich weiß, dass ich in der Lage sein sollte, $NFaber nicht sicher, wie es verwendet werden kann.

Und das scheint nicht zu funktionieren:

awk ' { print ( $NF-- )  } '
Brian G.
quelle
10
NFist der letzte $NF
Feldindex
das macht jetzt Sinn. Deshalb funktioniert wohl der Dollar außerhalb der Klammern
Brian G

Antworten:

279
awk '{print $(NF-1)}'

Sollte arbeiten

Chris Kannon
quelle
2
Das funktioniert bei mir nicht. Ich bekomme "Titel: 5: Befehl nicht gefunden: NF-1" in awk 3.1.8 unter Ubuntu.
Gurgeh
3
Ich würde das Pre / Post-Dekrement vermeiden, um sicherzustellen, dass Sie den Wert von $ NF nicht ändern
Gregory Patmore
Dies bricht ab, wenn Sie versuchen, das drittletzte Feld wieawk -F '.' '{print $(NF-2)}'
gies0r
3
@ Gurgeh: Dies geschieht, weil $(..)ein Befehl in einer Subshell aufgerufen wird, je nachdem, welche Shell Sie verwenden. Sie können dies umgehen, indem Sie $ (NF-1)anstelle von verwenden $(NF-1).
Wting
21

Kleine Ergänzung zu Chris Kannons akzeptierter Antwort: Nur drucken, wenn tatsächlich eine vorletzte Spalte vorhanden ist.

(
echo       | awk 'NF && NF-1 { print ( $(NF-1) ) }'
echo 1     | awk 'NF && NF-1 { print ( $(NF-1) ) }'
echo 1 2   | awk 'NF && NF-1 { print ( $(NF-1) ) }'
echo 1 2 3 | awk 'NF && NF-1 { print ( $(NF-1) ) }'
)
progz
quelle
15

Es ist am einfachsten:

 awk '{print $--NF}' 

Der Grund, warum das Original $NF--nicht funktioniert hat, ist, dass der Ausdruck vor dem Dekrement ausgewertet wird, während mein Präfix-Dekrement vor dem Auswerten ausgeführt wird.

Steve
quelle
Als Mnemonik ist dieses Verhalten dasselbe wie bei C / Java usw. int x = ++i int x = i++, Präfix bedeutet zuerst Inkrementieren; Postfix bedeutet späteres Inkrementieren (Zuweisung zuerst).
Wochenende
9
awk ' { print ( $(NF-1) ) }' file
Ghostdog74
quelle
4

Sie waren nicht weit vom Ergebnis entfernt! Das macht es:

awk '{NF--; print $NF}' file

Dies verringert die Anzahl der Felder in einem, so dass $NFdas vorletzte Feld enthalten ist.

Prüfung

Lassen Sie uns einige Zahlen generieren und sie in 5er-Gruppen drucken:

$ seq 12 | xargs -n5
1 2 3 4 5
6 7 8 9 10
11 12

Drucken wir das vorletzte in jede Zeile:

$ seq 12 | xargs -n5 | awk '{NF--; print $NF}'
4
9
11
fedorqui 'SO hör auf zu schaden'
quelle
3

Perl-Lösung ähnlich der awk-Lösung von Chris Kannon:

perl -lane 'print $F[$#F-1]' file

Diese Befehlszeilenoptionen werden verwendet:

  • n Schleife um jede Zeile der Eingabedatei, drucke nicht automatisch jede Zeile

  • l Entfernt Zeilenumbrüche vor der Verarbeitung und fügt sie anschließend wieder hinzu

  • aAutosplit-Modus - Teilen Sie die Eingabezeilen in das @FArray. Standardmäßig wird auf Leerzeichen aufgeteilt

  • e Führen Sie den Perl-Code aus

Das @FAutosplit-Array beginnt bei Index [0], während awk-Felder mit $ 1 beginnen.
$#Fist die Anzahl der Elemente in@F

Chris Koknat
quelle
1
oder verwenden Sie die negative Indexierung bereits von Perl ...$F[-2]
Sundeep
2

Haben Sie versucht, mit dem Befehl rev von rechts nach links zu beginnen? In diesem Fall müssen Sie nur die 2. Spalte drucken:

seq 12 | xargs -n5 | rev | awk '{ print $2}' | rev
4
9
11
Fdv
quelle
1

Dekrementiert zuerst den Wert und druckt ihn dann aus -

awk ' { print $(--NF)}' file

ODER

rev file|cut -d ' ' -f2|rev
VIPIN KUMAR
quelle
0

Wenn Sie viele Spalten haben und alle bis auf die drei Spalten in der letzten Spalte drucken möchten, kann dies hilfreich sein

awk '{ $NF="";$(NF-1)="";$(NF-2)="" ; print $0 }'

Sand1512
quelle