Jak wydrukować ostatnie dwie kolumny za pomocą awk


106

Chcę tylko wydrukować dwie ostatnie kolumny.


6
Nie do końca jestem pewien, dlaczego ma to 87 głosów za, z pewnością można to poprawić przynajmniej za pomocą przykładu.
— Arj

Prawdopodobnie dlatego, że pytanie jest z natury niezwykle proste i łatwe do zrozumienia bez przykładu, co jest rzadkością, ale w tym przypadku wydaje się działać. Myślę, że tutaj problemem nie jest brak informacji, ale raczej brak niezależnych badań.
— DryLabRebel

To pytanie jest również duplikatem tego pytania.
— DryLabRebel

Czy to odpowiada na twoje pytanie? Wydrukuj przedostatnią kolumnę / pole w awk
— DryLabRebel

Odpowiedzi:


194

Możesz skorzystać ze zmiennej, NFktóra jest ustawiona na całkowitą liczbę pól w rekordzie wejściowym:

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

przy założeniu, że masz co najmniej 2 pola.


1
Potrzebujesz przecinka - ponieważ jesteśmy dziś wybredni: spacja łączy pola, przecinek oddziela pola w instrukcji print. To połączy oba pola
— Jim Mcnamara

18
Teraz drukujesz "pole-OFS-tab-OFS-pole". Powinien być awk '{print $(NF-1) "\t" $NF}' filelub awk '{print $(NF-1), $NF}' filelub awk 'BEGIN{OFS="\t"} {print $(NF-1), $NF}' file.
— Wstrzymano do odwołania.

Aby dodać do poprzedniego komentarza, problem z użyciem '{print $x,"\t",$y}'polega na tym, że awk interpretuje każdą zmienną oddzieloną przecinkami jako swoje własne pole, więc wynikiem będzie faktycznie field1<space><tab><space>field2(ponieważ domyślnie użyje separatora spacji), w przeciwieństwie do field1<tab>field2tego, co prawdopodobnie spodziewasz się. używanie separatora pól wyjściowych (OFS) jest prawie zawsze tym, czego potrzebujesz.
— DryLabRebel

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

Uwaga: działa to tylko wtedy, gdy istnieją co najmniej dwie kolumny. W przypadku rekordów z jedną kolumną otrzymasz fałszywy"-1 column1"


3
Spróbuj i zobacz. Działa w Solaris 9 awk i nawk. Alternatywą jest $ (NF-1)
— jim mcnamara

1
@coaddict - Domyślam się, że nie pracowałeś z różnymi implementacjami awk. Stare zachowania awks zostały (być może błędnie) przeniesione do przodu. Nie mam gawk do testowania - do czego prawdopodobnie się odnosisz. Więc nie wiem na pewno, dlaczego twój komentarz został odrzucony. Linux awk po wyjęciu z pudełka to zwykle gawk. Przetestuję i wrócę. W międzyczasie spróbuj Soalris, HPUX, DGX lub czegokolwiek, aby zobaczyć, co mam na myśli przez stary awk.
— jim mcnamara

6
Prawdopodobnie zostałeś oszukany i pomyślałeś, że to działa, ponieważ próbowałeś echo 1 2 3 | awk .... $NF-1jest ($NF) - 1w każdej awkrealizacji.
— Stephane Chazelas

Kod źródłowy „One True Awk” zawiera ponad 40 konfliktów yaccgramatycznych, co jest ironiczne, biorąc pod uwagę znaczenie litery A w awk. Różne wersje awk inaczej analizują rzeczy? Wielka niespodzianka!
— Kaz,

1
@THESorcerer, spróbuj z echo '5 4 3 2 1' | awk '{print $NF-1,$NF; print $(NF-1), $NF}'- lub jakimkolwiek innym wejściem, w którym drugie ostatnie pole jest nie mniejsze niż ostatnie pole.
— glenn jackman

6

@jim McNamara: spróbuj użyć nawiasów dla dokoła NF, czyli $(NF-1)i $(NF)zamiast $NF-1a $NF(działa na Mac OS X 10.6.8 dla FreeBSD awki 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

Rozważaliśmy już () wcześniej. Myślałem, że dyskutujemy, skąd wzięło się oryginalne zachowanie starego awk.
— jim mcnamara

+1 za odpowiedź z wyraźnym $(NF-1)- co najmniej jest bardziej przenośne niż $NF-1; jest zdecydowanie mniej niejednoznaczny. $(NF)jest przesadą - po prostu wystarczy $NF. Warto też chronić się przed wierszami z mniej niż 2 kolumnami, ponieważ w przypadku wierszy jednokolumnowych wartość pierwszej kolumny zostanie wyświetlona dwukrotnie , a przy wierszach z zerową kolumną - tj. Pustych - polecenie awk całkowicie się nie powiedzie z powodu próby dostęp do pola o indeksie -1.
— mklement0

1

użycie gawk wykazuje 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

Właśnie umieściłem gawk na Solarisie 10 M4000: Więc, gawk jest cuplritem w kwestii $ NF-1 kontra $ (NF-1). Następne pytanie, co mówi POSIX? za:

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

Nie ma żadnego kierunku w jedną lub drugą stronę. Niedobrze. gawk implikuje odejmowanie, inne awks wymagają odejmowania lub numeru pola. hmm.


1
Pierwsze 2 wiersze przykładowego pliku wejściowego nie są pomocne, ponieważ dają takie same wyniki w obu przypadkach . Czy możesz potwierdzić, że Solaris awk rzeczywiście NIE zachowuje się w tym przypadku jak gawk?
— mklement0

Jeśli chodzi o twoje łącze do specyfikacji awk: niepotwierdzonym argumentem za użyciem $(NF-1)jest to, że oba przykłady obliczania indeksu pola w specyfikacji używają tej postaci: $(NF-1)i $(NF+2). Następnie jest sekcja „Wyrażenia w awk”, w której wymieniono $exprjako mające [znacznie] wyższy priorytet niż expr - expr. Ponieważ NFsamo w sobie jest wyrażeniem, $NF-1należy obliczyć ($NF)-1. Nawet JEŚLI w końcu istnieją implementacje awk, które oceniają $NF-1jako $(NF-1), wyciągnięta tutaj lekcja jest taka, że ​​używanie $(NF-1)jest bezpiecznym i przenośnym wyborem.
— mklement0

0

spróbuj z tym

$ 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

Spróbuj tego, aby wziąć pod uwagę wszystkie możliwe scenariusze:

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

lub

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

lub

awk '{print $(NF-1), $NF} {print $(NF-1), $NF}' file
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.