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

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ć


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

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ą.


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


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

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


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

1

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

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

LUB

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

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

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.