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ń.
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"
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
1223-1 one
-1 three
# cat filename1223
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:
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.
Odpowiedzi:
Możesz skorzystać ze zmiennej,
NF
która jest ustawiona na całkowitą liczbę pól w rekordzie wejściowym:przy założeniu, że masz co najmniej 2 pola.
źródło
awk '{print $(NF-1) "\t" $NF}' file
lubawk '{print $(NF-1), $NF}' file
lubawk 'BEGIN{OFS="\t"} {print $(NF-1), $NF}' file
.'{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 faktyczniefield1<space><tab><space>field2
(ponieważ domyślnie użyje separatora spacji), w przeciwieństwie dofield1<tab>field2
tego, co prawdopodobnie spodziewasz się. używanie separatora pól wyjściowych (OFS) jest prawie zawsze tym, czego potrzebujesz.Uwaga: działa to tylko wtedy, gdy istnieją co najmniej dwie kolumny. W przypadku rekordów z jedną kolumną otrzymasz fałszywy
"-1 column1"
źródło
echo 1 2 3 | awk ...
.$NF-1
jest($NF) - 1
w każdejawk
realizacji.yacc
gramatycznych, co jest ironiczne, biorąc pod uwagę znaczenie litery A w awk. Różne wersje awk inaczej analizują rzeczy? Wielka niespodzianka!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.@jim McNamara: spróbuj użyć nawiasów dla dokoła
NF
, czyli$(NF-1)
i$(NF)
zamiast$NF-1
a$NF
(działa na Mac OS X 10.6.8 dla FreeBSDawk
igawk
).źródło
$(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.użycie gawk wykazuje problem:
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:
Nie ma żadnego kierunku w jedną lub drugą stronę. Niedobrze. gawk implikuje odejmowanie, inne awks wymagają odejmowania lub numeru pola. hmm.
źródło
$(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$expr
jako mające [znacznie] wyższy priorytet niżexpr - expr
. PonieważNF
samo w sobie jest wyrażeniem,$NF-1
należy obliczyć($NF)-1
. Nawet JEŚLI w końcu istnieją implementacje awk, które oceniają$NF-1
jako$(NF-1)
, wyciągnięta tutaj lekcja jest taka, że używanie$(NF-1)
jest bezpiecznym i przenośnym wyborem.spróbuj z tym
źródło
Spróbuj tego, aby wziąć pod uwagę wszystkie możliwe scenariusze:
lub
lub
źródło