So drucken Sie die letzten beiden Spalten mit awk

106

Ich möchte nur die letzten beiden Spalten drucken.

vehomzzz
quelle
6
Ich bin mir nicht ganz sicher, warum dies 87 positive Stimmen hat, aber es kann zumindest mit einem Beispiel verbessert werden.
Arj
Wahrscheinlich, weil die Frage von Natur aus extrem einfach und ohne ein Beispiel leicht verständlich ist, was selten vorkommt, aber in diesem Fall scheint es zu funktionieren. Das Problem hier ist nicht der Mangel an Informationen, sondern vielmehr der Mangel an unabhängiger Forschung.
DryLabRebel vor
Diese Frage ist auch ein Duplikat dieser Frage.
DryLabRebel vor
Beantwortet das deine Frage? Vorletzte Spalte / Feld in awk
DryLabRebel vor

Antworten:

194

Sie können eine Variable verwenden, NFdie auf die Gesamtzahl der Felder im Eingabedatensatz festgelegt ist:

awk '{print $(NF-1),"\t",$NF}' file

Dies setzt voraus, dass Sie mindestens 2 Felder haben.

Codaddict
quelle
1
Sie brauchen ein Komma - da wir heute wählerisch sind: Leerzeichen verketten Felder, Komma trennt Felder in einer print-Anweisung. Das wird die beiden Felder zusammenführen
Jim Mcnamara
18
Jetzt drucken Sie "Feld-OFS-Tab-OFS-Feld". Es sollte awk '{print $(NF-1) "\t" $NF}' fileoder awk '{print $(NF-1), $NF}' fileoder sein awk 'BEGIN{OFS="\t"} {print $(NF-1), $NF}' file.
Bis auf weiteres angehalten.
Um den vorherigen Kommentar zu ergänzen, besteht das Problem bei der Verwendung '{print $x,"\t",$y}'darin, dass awk jede durch Kommas getrennte Variable als eigenes Feld interpretiert, sodass das Ergebnis tatsächlich field1<space><tab><space>field2ist (da standardmäßig ein Leerzeichen-Trennzeichen verwendet wird), im Gegensatz zu field1<tab>field2dem , was wahrscheinlich das ist Sie erwarten. Die Verwendung von Output Field Separator (OFS) ist fast immer das, was Sie wollen.
DryLabRebel vor
13
awk '{print $NF-1, $NF}'  inputfile

Hinweis: Dies funktioniert nur, wenn mindestens zwei Spalten vorhanden sind. Bei Datensätzen mit einer Spalte erhalten Sie eine falsche"-1 column1"

Jim Mcnamara
quelle
3
Versuchen Sie es und sehen Sie. Es funktioniert Solaris 9 awk & nawk. Die Alternative ist $ (NF-1)
Jim Mcnamara
1
@coaddict - Ich vermute, Sie haben nicht mit verschiedenen awk-Implementierungen gearbeitet. Altes Verhalten wurde (möglicherweise fälschlicherweise) vorgebracht. Ich habe kein Gawk zum Testen - worauf Sie sich wahrscheinlich beziehen. Ich weiß also nicht genau, warum Ihr Kommentar abgelehnt wurde. Linux awk out of the box ist normalerweise gawk. Ich werde testen und zurück posten. Versuchen Sie in der Zwischenzeit Soalris oder HPUX oder DGX oder was auch immer, um zu sehen, was ich mit altem awk meine.
Jim Mcnamara
6
Sie wurden wahrscheinlich dazu gebracht zu glauben, dass es funktioniert hat, weil Sie es versucht haben echo 1 2 3 | awk .... $NF-1ist ($NF) - 1in jeder awkImplementierung.
Stephane Chazelas
Der Quellcode "One True Awk" hat mehr als 40 Konflikte in der yaccGrammatik, was ironisch ist, wenn man bedenkt, wofür das A in awk steht. Verschiedene Versionen von awk, die Dinge unterschiedlich analysieren? Große Überraschung!
Kaz
1
@THESorcerer, versuchen Sie es mit echo '5 4 3 2 1' | awk '{print $NF-1,$NF; print $(NF-1), $NF}'- oder einer anderen Eingabe, bei der das vorletzte Feld nicht kleiner als das letzte Feld ist.
Glenn Jackman
6

@jim mcnamara: Verwenden Sie Klammern für around NF, dh $(NF-1)und $(NF)anstelle von $NF-1und $NF(funktioniert unter Mac OS X 10.6.8 für FreeBSD awkund gawk).

echo '
1 2
2 3
one
one two three
' | gawk '{if (NF >= 2) print $(NF-1), $(NF);}'

# output:
# 1 2
# 2 3
# two three
Guzo
quelle
Wir hatten bereits früher über () nachgedacht. Ich dachte, wir diskutieren, woher das ursprüngliche alte awk-Verhalten kommt.
Jim Mcnamara
+1 für eine explizite Antwort $(NF-1)- die zumindest portabler ist als $NF-1; es ist definitiv weniger mehrdeutig. $(NF)ist allerdings übertrieben - reicht einfach aus $NF. Das Schützen vor Zeilen mit weniger als 2 Spalten lohnt sich ebenfalls, da bei einspaltigen Zeilen der erste Spaltenwert zweimal angezeigt wird und bei nullspaltigen, dh leeren Zeilen der Befehl awk aufgrund eines Versuchs insgesamt fehlschlägt um auf ein Feld mit dem Index -1 zuzugreifen.
mklement0
1

Die Verwendung von Gawk zeigt das Problem:

 gawk '{ print $NF-1, $NF}' filename
1 2
2 3
-1 one
-1 three
# cat filename
1 2
2 3
one
one two three

Ich habe gerade Solaris 10 M4000 gawk: Also, gawk ist der Cuplrit in der Frage $ NF-1 vs. $ (NF-1). Nächste Frage, was sagt POSIX? pro:

http://www.opengroup.org/onlinepubs/009695399/utilities/awk.html

Es gibt keine Richtung in die eine oder andere Richtung. Nicht gut. gawk impliziert Subtraktion, andere awks implizieren Feldnummer oder Subtraktion. hmm.

Jim Mcnamara
quelle
1
Die ersten beiden Zeilen Ihrer Beispieleingabedatei sind nicht hilfreich, da sie bei beiden Verhaltensweisen dieselbe Ausgabe erzeugen . Können Sie bitte erneut bestätigen, dass sich Solaris awk in diesem Fall tatsächlich NICHT wie gawk verhält?
mklement0
Was Ihren Link zur awk-Spezifikation betrifft: Das anekdotische Argument für die Verwendung $(NF-1)ist, dass die beiden Beispiele für die Berechnung des Feldindex in der Spezifikation beide diese Form verwenden: $(NF-1)und $(NF+2). Dann gibt es den Abschnitt "Ausdrücke in awk", in dem $expr[viel] Vorrang als aufgeführt ist expr - expr. Da NFist ein Ausdruck selbst, $NF-1sollte zu bewerten ($NF)-1. Selbst wenn es tatsächlich awk-Implementierungen gibt, die $NF-1als bewertet werden $(NF-1), ist die hier gewonnene Erkenntnis, dass die Verwendung $(NF-1)die sichere und tragbare Wahl ist.
mklement0
0

versuche es damit

$ cat /tmp/topfs.txt
/dev/sda2      xfs        32G   10G   22G  32% /

awk print last column
$ cat /tmp/topfs.txt | awk '{print $NF}'

awk print before last column
$ cat /tmp/topfs.txt | awk '{print $(NF-1)}'
32%

awk - print last two columns
$ cat /tmp/topfs.txt | awk '{print $(NF-1), $NF}'
32% /
namasivayam.cse
quelle
0

Bitte probieren Sie dies aus, um alle möglichen Szenarien zu berücksichtigen:

awk '{print $(NF-1)"\t"$NF}'  file

oder

awk 'BEGIN{OFS="\t"}' file

oder

awk '{print $(NF-1), $NF} {print $(NF-1), $NF}' file
Marios Karamanis
quelle