Wydrukuj przedostatnią kolumnę / pole w awk

164

Chcę wydrukować przedostatnią kolumnę lub pole w awk. Liczba pól jest zmienna. Wiem, że powinienem móc go używać, $NFale nie jestem pewien, jak można go używać.

I to nie wydaje się działać:

awk ' { print ( $NF-- )  } '
Brian G.
źródło
10
NFto ostatni indeks pola, $NFto wartość ostatniego pola
glenn jackman
to ma teraz sens. dlatego myślę, że dolar poza nawiasem działa
Brian G,

Odpowiedzi:

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

Powinno działać

Chris Kannon
źródło
2
To nie działa dla mnie. Otrzymuję „title: 5: command not found: NF-1” w awk 3.1.8 pod Ubuntu.
Gurgeh
3
Unikałbym dekrementacji przed / po, aby upewnić się, że nie zmienisz wartości $ NF
Gregory Patmore
To się psuje, jeśli spróbujesz uzyskać trzecie ostatnie pole, takie jakawk -F '.' '{print $(NF-2)}'
gies0r
3
@Gurgeh: Dzieje się tak, ponieważ $(..)wywołuje polecenie w podpowłoce w zależności od używanej powłoki. Możesz obejść ten problem, używając $ (NF-1)zamiast $(NF-1).
wting
21

Drobny dodatek do zaakceptowanej odpowiedzi Chrisa Kannona: drukuj tylko wtedy, gdy faktycznie istnieje przedostatnia kolumna.

(
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
źródło
15

To najprostsze:

 awk '{print $--NF}' 

Przyczyną, dla której oryginał $NF--nie działał, jest to, że wyrażenie jest obliczane przed dekrementacją, podczas gdy moja dekrementacja przedrostka jest wykonywana przed oceną.

Steve
źródło
Jako mnemonik to zachowanie jest takie samo jak C / Java itp. int x = ++i int x = i++, Przedrostek oznacza najpierw inkrementację; postfix oznacza późniejszy przyrost (najpierw przypisanie).
Weekend
9
awk ' { print ( $(NF-1) ) }' file
ghostdog74
źródło
4

Nie byłeś daleko od wyniku! Robi to:

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

To zmniejsza liczbę pól w jednym, tak więc $NF zawiera poprzednie przedostatnie.

Test

Wygenerujmy kilka liczb i wydrukujmy je w grupach po 5:

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

Wypiszmy przedostatni w każdym wierszu:

$ seq 12 | xargs -n5 | awk '{NF--; print $NF}'
4
9
11
fedorqui 'SO przestań szkodzić'
źródło
3

Rozwiązanie Perla podobne do rozwiązania awk Chrisa Kannona:

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

Używane są następujące opcje wiersza polecenia:

  • n pętla wokół każdego wiersza pliku wejściowego, nie drukuj automatycznie każdego wiersza

  • l usuwa nowe wiersze przed przetworzeniem i dodaje je później

  • atryb autosplit - dzielenie linii wejściowych na @Ftablicę. Domyślnie dzielenie na białe znaki

  • e wykonać kod perla

@FTablica autosplit rozpoczyna się indeksem [0], gdy pola awk zacząć od 1 $.
$#Fto liczba elementów w@F

Chris Koknat
źródło
1
lub użyj ujemnego indeksowania już dostarczonego przez perl ...$F[-2]
Sundeep
2

Czy próbowałeś zacząć od prawej do lewej za pomocą polecenia rev? W takim przypadku wystarczy wydrukować drugą kolumnę:

seq 12 | xargs -n5 | rev | awk '{ print $2}' | rev
4
9
11
Fdv
źródło
1

Najpierw zmniejsza wartość, a następnie ją drukuje -

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

LUB

rev file|cut -d ' ' -f2|rev
VIPIN KUMAR
źródło
0

Jeśli masz wiele kolumn i chcesz wydrukować wszystkie, ale nie wszystkie trzy cloumns w ostatnim, może to pomóc

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

Piasek1512
źródło