Jak wydrukować trzecią kolumnę do ostatniej kolumny?


121

Próbuję usunąć pierwsze dwie kolumny (którymi nie jestem zainteresowany) z pliku dziennika DbgView. Nie mogę znaleźć przykładu, który drukuje od kolumny 3 do końca wiersza. Zauważ, że każda linia ma zmienną liczbę kolumn.


możliwy duplikat
— użycia

Odpowiedzi:


108

... lub prostsze rozwiązanie: cut -f 3- INPUTFILE po prostu dodaj właściwy separator (-d) i uzyskasz ten sam efekt.


9
Zauważ, że działa to tylko wtedy, gdy separator jest dokładnie taki sam we wszystkich kolumnach ... Na przykład nie możesz użyć wycinania z separatorem takim jak \ d +. (O czym wiem.)
— Zach Wily

72
Gdy pytanie ma tytuł awk, przyjmowanie odpowiedzi innej niż awk jest niewłaściwe. A jeśli ludzie będą potrzebować tego do skryptów awk? Ta odpowiedź powinna być tylko komentarzem.
— syaz

24
@SyaZ: Normalnie się zgadzam, ale biorąc pod uwagę ilość „darmowych awk” na tej tablicy, pomyślałem, że trzeba pokazać alternatywny sposób wykonania zadania. Czy nie byłbyś wdzięczny, gdyby ktoś pokazał ci prostszy i szybszy sposób wykonania tego samego zadania? Może plakat pomyślał, że awk jest jedynym sposobem na zrobienie tego ze względu na liczbę odpowiedzi „niepoprawnych, ale z pewnością możliwych do ulepszenia” na inne pytania?
— Marcin

12
Po to jest ten komentarz. Zaakceptuj najlepszą odpowiedź awk i podaj lepsze sugestie nie-awk w komentarzach. Jeśli ludzie zaczną publikować odpowiedzi, które nie odpowiadają dokładnie na pytania, będzie to denerwujące podczas wyszukiwania (w moim przypadku).
— syaz

12
Nie tylko separator musi być taki sam we wszystkich kolumnach, ale między kolumnami musi znajdować się DOKŁADNIE JEDEN separator. Więc jeśli masz do czynienia z programami, które dopasowują swoje wyjście do ograniczników, lepiej jest użyć awk.
— sknaumov

112
awk '{for(i=3;i<=NF;++i)print $i}' 

3
awk '{for (i = 3; i <= NF; ++ i) print $ i}' jest bardziej zwarty. :)
— user172818

1
Dzięki, lh3. Właśnie kopiowałem i wklejałem do podręcznika gawk. :)
— Jonathan Feinberg

23
to kończy się niepowodzeniem z wieloma wierszami, każda kolumna jest traktowana jako nowa linia podczas drukowania iwth print
— meso_2600

13
Aby rozwiązać problem z podzielonym wyjściem, proponuję następujące rozwiązanie: awk '{for(i=3;i<=NF;++i)printf $i""FS ; print ""}'( printfnie wydrukuje znaku nowej linii, podczas gdy print ""doda znak nowej linii po wydrukowaniu innych pól)
— lauhub

1
Czyli echo $(seq 1 10) | awk '{for (i=3; i<=NF; i++) printf $i FS}', co daje: 3 4 5 6 7 8 9 10.
— x-yuri

106
awk '{ print substr($0, index($0,$3)) }'

rozwiązanie znalezione tutaj:
http://www.linuxquestions.org/questions/linux-newbie-8/awk-print-field-to-end-and-character-count-179078/


23
Trochę się spóźniłem, ale to nie zadziała dla rekordów, w których pierwsze lub drugie pole jest równe trzeciemu (np. 3 2 3 4 5)
— aleph_null

drukowanie zakresu wewnętrznego jest również możliwe: `` # od 3 $ (w zestawie) do 6 $ (bez); echo "1,2,3,4,5,6,7,8,9" | awk 'BEGIN {FS = ","; OFS = ","} {print substr ($ 0, index ($ 0, $ 3), length ($ 0) -index ($ 0, $ 6) -1)}'; # daje 3,4,5 '' '
— splaisan

34

Odpowiedź Jonathana Feinberga drukuje każde pole w oddzielnym wierszu. Możesz użyć printfdo odbudowania rekordu do wyjścia w tym samym wierszu, ale możesz też po prostu przesunąć pola o skok w lewo.

awk '{for (i=1; i<=NF-2; i++) $i = $(i+2); NF-=2; print}' logfile

1
Należy pamiętać, że działa to tylko dla Gnu awk, dekrementacja NFnie jest dozwolona przez POSIX.
— kvantour

1
@kvantour: Działa w gawk, mawk, MacOS awk (nawk?). Wydaje się, że POSIX milczy na temat tego, czy NFmożna go zmniejszyć.
— Wstrzymano do odwołania.

To jeden z tych śmiesznych mrocznych zakamarków awk .
— kvantour

19
awk '{$1=$2=$3=""}1' file

Uwaga: ta metoda pozostawi "puste miejsca" w polach 1, 2, 3, ale nie stanowi problemu, jeśli chcesz tylko spojrzeć na wynik.


Śledź to polecenie za pomocą `| sed s / ^ \ * // | kolumna -t`, aby usunąć spacje wiodące i wyrównać pozostałe kolumny
— MSpreij

Co to ostatnie 1oznacza? które słowo kluczowe powinienem wyszukiwać awk?
— Itachi,


1
@Nathan, rozwiązujesz ten problem jako{$1=$2=$3="";$0=$0;$1=$1}1
— kvantour

11

Jeśli chcesz wydrukować kolumny po trzeciej, na przykład w tym samym wierszu, możesz użyć:

awk '{for(i=3; i<=NF; ++i) printf "%s ", $i; print ""}'

Na przykład:

Mar 09:39 20180301_123131.jpg
Mar 13:28 20180301_124304.jpg
Mar 13:35 20180301_124358.jpg
Feb 09:45 Cisco_WebEx_Add-On.dmg
Feb 12:49 Docker.dmg
Feb 09:04 Grammarly.dmg
Feb 09:20 Payslip 10459 %2828-02-2018%29.pdf

Wydrukuje:

20180301_123131.jpg
20180301_124304.jpg
20180301_124358.jpg
Cisco_WebEx_Add-On.dmg
Docker.dmg
Grammarly.dmg
Payslip 10459 %2828-02-2018%29.pdf

Jak widać, odcinek wypłaty, nawet ze spacją, jest wyświetlany we właściwej linii.


Szybki i elegancki. Dzięki;)
— 9nz9

To jest doskonałe, z wyjątkiem tego, że mam problem z wykluczeniem $ NF. Kiedy ustawiam warunek (<= NF), otrzymuję ostatnie pole, ale pierwszy znak pierwszego pola jest ucinany. Czy nie rozumiem czegoś pod względem funkcjonalności?
— Ken Ingram

Wygląda na to, że moim problemem jest to, że ^ M utknęło na końcu ostatniej kolumny. Nie widzę, jak to usunąć.
— Ken Ingram

8

A co z następującym wierszem:

awk '{1 $ = 2 $ = 3 $ = ""; Wydrukuj plik

Na podstawie sugestii @ ghostdog74. Mój powinien zachowywać się lepiej, gdy filtrujesz linie, tj .:

awk '/ ^ exim4-config / {$ 1 = ""; Wydrukuj plik

Krótkie i proste. Można również sed 's/\s\+//g'
— potokować

8
awk -v m="\x0a" -v N="3" '{$N=m$N ;print substr($0, index($0,m)+1)}'

To odcina to, co znajduje się przed danym polem nr., N i wypisuje całą resztę wiersza, łącznie z polem nr N i zachowując oryginalne odstępy (nie zmienia formatowania). Nie ma znaczenia, czy ciąg pola pojawia się również gdzie indziej w wierszu, co jest problemem z odpowiedzią daisaa.

Zdefiniuj funkcję:

fromField () { 
awk -v m="\x0a" -v N="$1" '{$N=m$N; print substr($0,index($0,m)+1)}'
}

I użyj tego w ten sposób:

$ echo "  bat   bi       iru   lau bost   " | fromField 3
iru   lau bost   
$ echo "  bat   bi       iru   lau bost   " | fromField 2
bi       iru   lau bost 

Dane wyjściowe zachowują wszystko, w tym spacje końcowe

Działa dobrze w przypadku plików, w których „/ n” jest separatorem rekordów, więc nie ma znaku nowego wiersza w wierszach. Jeśli chcesz go używać z innymi separatorami rekordów, użyj:

awk -v m="\x01" -v N="3" '{$N=m$N ;print substr($0, index($0,m)+1)}'

na przykład. Działa dobrze z prawie wszystkimi plikami, o ile nie używają szesnastkowego znaku nr. 1 wewnątrz linii.


4

Następujące polecenie awk drukuje N ostatnich pól każdego wiersza, a na końcu wiersza drukuje znak nowego wiersza:

awk '{for( i=6; i<=NF; i++ ){printf( "%s ", $i )}; printf( "\n"); }'

Znajdź poniżej przykład, który wymienia zawartość katalogu / usr / bin, a następnie przechowuje ostatnie 3 wiersze, a następnie wypisuje ostatnie 4 kolumny każdego wiersza przy użyciu awk:

$ ls -ltr /usr/bin/ | tail -3
-rwxr-xr-x 1 root root       14736 Jan 14  2014 bcomps
-rwxr-xr-x 1 root root       10480 Jan 14  2014 acyclic
-rwxr-xr-x 1 root root    35868448 May 22  2014 skype

$ ls -ltr /usr/bin/ | tail -3 | awk '{for( i=6; i<=NF; i++ ){printf( "%s ", $i )}; printf( "\n"); }'
Jan 14 2014 bcomps 
Jan 14 2014 acyclic 
May 22 2014 skype

4
awk '{a=match($0, $3); print substr($0,a)}'

Najpierw znajdź pozycję początku trzeciej kolumny. Za pomocą substr wypisujesz całą linię ($ 0) zaczynając od pozycji (w tym przypadku a) do końca linii.


3

Cóż, możesz łatwo osiągnąć ten sam efekt, używając wyrażenia regularnego. Zakładając, że separator jest spacją, wyglądałoby to tak:

awk '{ sub(/[^ ]+ +[^ ]+ +/, ""); print }'

1
Unikałbym wyrażenia regularnego. Prawdopodobnie wolniej i łatwiej przypadkowo zepsuć.
— Cascabel

1
Skraca to w ten sposób: awk '{ sub(/([^ ]+ +){2}/, ""); print }'co dwa razy usuwa wzór.
— erik


2

Rozwiązanie Perl:

perl -lane 'splice @F,0,2; print join " ",@F' 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 tablicę @F. Domyślnie dzielenie na białe znaki

  • -e wykonać kod perla

splice @F,0,2 czysto usuwa kolumny 0 i 1 z tablicy @F

join " ",@F łączy elementy tablicy @F, używając spacji między każdym elementem

Jeśli plik wejściowy jest rozdzielany przecinkami, a nie spacjami, użyj -F, -lane


Rozwiązanie w Pythonie:

python -c "import sys;[sys.stdout.write(' '.join(line.split()[2:]) + '\n') for line in sys.stdin]" < file


1

Trochę późno tutaj, ale żadne z powyższych nie wydawało się działać. Spróbuj tego, używając printf, wstawia spacje między nimi. Zdecydowałem się nie mieć znaku nowej linii na końcu.

awk '{for(i=3;i<=NF;++i) printf("%s ",  $i) }'

1
awk '{for (i=4; i<=NF; i++)printf("%c", $i); printf("\n");}'

drukuje rekordy począwszy od czwartego pola do ostatniego pola w tej samej kolejności, w jakiej znajdowały się w oryginalnym pliku


przepraszam, to nie była całkiem poprawna odpowiedź. jest zbyt szczegółowy, ale nie wiem, jak go usunąć
— Massimo


0

Jeśli chodzi tylko o zignorowanie pierwszych dwóch pól i jeśli nie chcesz spacji podczas maskowania tych pól (tak jak robią to niektóre z powyższych odpowiedzi):

awk '{gsub($1" "$2" ",""); print;}' file

0
awk '{$1=$2=""}1' FILENAME | sed 's/\s\+//g'

Pierwsze dwie kolumny są wyczyszczone, sedusuwa spacje wiodące.


-2

W kolumnach AWK nazywane są polami, stąd kluczem jest NF

wszystkie rzędy:

awk -F '<column separator>' '{print $(NF-2)}' <filename>

tylko pierwszy rząd:

awk -F '<column separator>' 'NR<=1{print $(NF-2)}' <filename>
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.