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.