Come stampare le ultime due colonne usando awk


106

Voglio solo stampare le ultime due colonne.


6
Non del tutto sicuro del motivo per cui questo ha 87 voti positivi, può certamente essere migliorato con un esempio come minimo.
Arj

Probabilmente perché la domanda è estremamente semplice per natura e facilmente comprensibile senza un esempio, il che è raro, ma in questo caso sembra funzionare. Il problema qui non è la mancanza di informazioni credo, ma più che mostra una mancanza di ricerca indipendente.
DryLabRebel

Questa domanda è anche un duplicato di questa domanda.
DryLabRebel

Questo risponde alla tua domanda? Stampa la penultima colonna / campo in awk
DryLabRebel

Risposte:


194

È possibile utilizzare la variabile NFimpostata sul numero totale di campi nel record di input:

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

questo presuppone che tu abbia almeno 2 campi.


1
Hai bisogno di una virgola - dato che oggi siamo pignoli: lo spazio concatena i campi, la virgola separa i campi in un'istruzione print. Ciò unirà i due campi
jim mcnamara,

18
Ora stai stampando "field-OFS-tab-OFS-field". Dovrebbe essere awk '{print $(NF-1) "\t" $NF}' fileo awk '{print $(NF-1), $NF}' fileo awk 'BEGIN{OFS="\t"} {print $(NF-1), $NF}' file.
In pausa fino a nuovo avviso.

Giusto per aggiungere al commento precedente, il problema con l'utilizzo '{print $x,"\t",$y}'è che awk interpreta ogni variabile separata da virgole come il proprio campo, quindi il risultato sarà effettivamente field1<space><tab><space>field2, (perché userà delimitatore di spazio bianco per impostazione predefinita) al contrario di quello field1<tab>field2che è probabilmente ciò ti aspetti. usare Output Field Separator (OFS) è quasi sempre quello che vuoi.
DryLabRebel

13
awk '{print $NF-1, $NF}'  inputfile

Nota: funziona solo se esistono almeno due colonne. Sui record con una colonna otterrai un falso"-1 column1"


3
Prova e guarda. Funziona Solaris 9 awk & nawk. L'alternativa è $ (NF-1)
jim mcnamara,

1
@coaddict - Immagino che tu non abbia lavorato con diverse implementazioni di awk. I vecchi comportamenti di awk sono stati (forse erroneamente) portati avanti. Non ho gawk su cui testare, che è probabilmente ciò a cui ti riferisci. Quindi non so con certezza perché il tuo commento sia stato inserito. Linux awk out of the box di solito è gawk. Proverò e pubblicherò. Nel frattempo prova Soalris o HPUX o DGX o qualsiasi altra cosa per vedere cosa intendo per vecchio awk.
jim mcnamara

6
Probabilmente sei stato indotto a pensare che funzionasse perché ci hai provato echo 1 2 3 | awk .... $NF-1è ($NF) - 1in ogni awkimplementazione.
Stephane Chazelas

Il codice sorgente di "One True Awk" ha più di 40 conflitti nella yaccgrammatica, il che è ironico dato ciò che la A sta per in awk. Versioni diverse di awk che analizzano le cose in modo diverso? Grande sorpresa!
Kaz

1
@THESorcerer, prova con echo '5 4 3 2 1' | awk '{print $NF-1,$NF; print $(NF-1), $NF}'- o qualsiasi altro input in cui il penultimo campo non è uno in meno dell'ultimo campo.
glenn jackman

6

McNamara @jim: provare a utilizzare parentesi per circa NF, vale a dire $(NF-1)e $(NF)invece di $NF-1e $NF(funziona su Mac OS X 10.6.8 per FreeBSD awke 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

Avevamo già considerato () in precedenza. Pensavo stessimo discutendo dell'origine del vecchio comportamento awk originale.
jim mcnamara

+1 per una risposta con esplicito $(NF-1)- che almeno è più portabile di $NF-1; è decisamente meno ambiguo. $(NF)è eccessivo, però, basta $NF. Vale anche la pena proteggersi dalle righe con meno di 2 colonne, poiché con le righe di una colonna si otterrebbe il valore della prima colonna due volte , e con le righe a colonna zero, ovvero vuote, il comando awk fallirebbe del tutto, a causa di un tentativo per accedere a un campo con indice -1.
mklement0

1

l'utilizzo di gawk mostra il problema:

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

Ho appena messo gawk su Solaris 10 M4000: Quindi, gawk è il cuplrit sul problema $ NF-1 contro $ (NF-1). Prossima domanda cosa dice POSIX? per:

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

Non c'è direzione in un modo o nell'altro. Non bene. gawk implica sottrazione, altri awk implicano numero di campo o sottrazione. hmm.


1
Le prime 2 righe del file di input di esempio non sono utili in quanto producono lo stesso output con entrambi i comportamenti. Puoi riconfermare che Solaris awk NON si comporta davvero come gawk in questo caso?
mklement0

Per quanto riguarda il tuo collegamento alle specifiche awk: L'argomento aneddotico per l'utilizzo $(NF-1)è che i due esempi di calcolo dell'indice di campo nella specifica utilizzano entrambi quella forma: $(NF-1)e $(NF+2). Poi c'è la sezione "Espressioni in awk", che elenca $exprcome aventi precedenza [molto] più alta di expr - expr. Poiché NFè un'espressione stessa, $NF-1dovrebbe restituire ($NF)-1. Anche SE, dopo tutto, ci sono davvero implementazioni awk là fuori che valutano $NF-1come $(NF-1), la lezione appresa qui è che l'uso $(NF-1)è la scelta sicura e portatile.
mklement0

0

prova con questo

$ 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% /

0

Prova questo per tenere conto di tutti i possibili scenari:

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

o

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

o

awk '{print $(NF-1), $NF} {print $(NF-1), $NF}' file
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.