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-- )  } '

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


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) ) }'
)

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.


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


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

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


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

1

Dekrementiert zuerst den Wert und druckt ihn dann aus -

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

ODER

rev file|cut -d ' ' -f2|rev

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 }'

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.