Jak wydrukować wszystkie kolumny po określonej liczbie za pomocą awk?

90

W powłoce potokuję do awk, gdy potrzebuję określonej kolumny.

Spowoduje to wydrukowanie kolumny 9, na przykład:

... | awk '{print $9}'

Jak mogę powiedzieć awk, żeby wypisał wszystkie kolumny, włączając i po kolumnie 9 , a nie tylko kolumnę 9?

Lazer
źródło
1
możliwy duplikat

Odpowiedzi:

83
awk '{ s = ""; for (i = 9; i <= NF; i++) s = s $i " "; print s }'
Amadan
źródło
3
kilka drobnych poprawek:awk -v N=9 '{sep=""; for (i=N; i<=NF; i++) {printf("%s%s",sep,$i); sep=OFS}; printf("\n")}'
glenn jackman
Dzięki @glenn, to rzeczywiście trochę bardziej ogólne. W każdym razie - zdecydowanie się zgodzę, że lepiej byłoby użyć cutlub perldo tego. Używaj tego tylko wtedy, gdy naprawdę nalegasz na to, aby go mieć awk.
Amadan
1
@SiegeX: Nie dodaje bajtów NUL, pozostawia FS na miejscu między każdym pustym polem.
Wstrzymano do odwołania.
1
Zobacz odpowiedź @ Ascherer na elegancję.
3
@veryhungrymike: Elegancja jest fajna, ale wolałbym mieć rację. : p
Amadan
68

Jeśli chcesz wykonać szereg pól, awknie ma na to prostego sposobu. cutZamiast tego polecam :

cut -d' ' -f 9- ./infile

Edytować

Dodano ogranicznik spacji, ponieważ domyślnie jest to tabulator. Dzięki Glenn za wskazanie tego

SiegeX
źródło
15
Jedną z rzeczy w wycinaniu jest to, że używa określonego separatora (domyślnie tabulatora), gdzie awk używa „białych znaków”. W przypadku wycięcia 2 kolejne tabulatory ograniczają puste pole.
glenn jackman
1
Jak zauważył @glennjackman, ogranicznikiem awk jest „biały znak” (również dowolna kwota). Zatem ustawienie ogranicznika cięcia na pojedynczą spację również nie pasowałoby do zachowania. niestety pętla jest najlepsza, jaką można zrobić, więc wygląda.
poncha
Ten nie działa poprawnie. Wypróbuj polecenie find . | xargs ls -l | cut -d' ' -f 9-. Z jakiegoś powodu liczone są również podwójne spacje. Przykład: lrwxrwxrwx 1 me me 21 Dec 12 00:00 ./file_a lrwxrwxrwx 1 me me 64 Dec 6 00:06 ./file_bspowoduje./file_a 00:06 ./file_b
Marco Pashkov
@MarcoPashkov proszę rozwinąć Ten nie działa poprawnie , zwłaszcza biorąc pod uwagę, że używasz dokładnie tego samego kodu w swoim potoku. Nawiasem mówiąc, nigdy nie
SiegeX
cięcie nie działa tutaj. Na przykład, jeśli dane wejściowe to „foo bar” (pojedyncza spacja) dla jednej linii i „foo ___ bar” (tj. Wiele spacji, ale SO jest zbyt sprytne, aby to pokazać) dla innej, cut przetworzy je inaczej.
UKMonkey
54
awk '{print substr($0, index($0,$9))}'

Edycja : Uwaga, to nie działa, jeśli jakiekolwiek pole przed dziewiątą zawiera taką samą wartość jak dziewiąta.

Ascherer
źródło
3
ten jest genialny!
10
@veryhungrymike: ... i nie działa, jeśli jakiekolwiek pole przed dziewiątą wartością zawiera taką samą wartość jak dziewiąta.
Amadan
6
Prawdopodobnie z powodu klasycznego zdania „miejmy nadzieję, że Twój plik nie zawiera tego problemu”. To absolutne nie-nie w inżynierii s / w stwierdzenie: „nie będziemy tracić czasu na sprawdzanie błędów pod kątem np. Wartości ujemnych, ponieważ„ mamy nadzieję, że użytkownik będzie wystarczająco inteligentny, aby ich nie wypróbować ”, awaria naszego narzędzia „”. HAHAHA! Zawsze miło mi to słyszeć! (I jak poczucie humoru), a także, jak idioci zrobić istnieje, to obowiązkiem dewelopera, aby jego rzeczy idiota-dowód ! Zamiast „liczyć na dobro w człowieku”. To raczej postawa oczekiwana od filozofów, a nie od s / w inżynierów ... LOL
błąd składniowy
3
Nie mówiłem, żeby nie sprawdzać błędów, ale jeśli wiesz, że nie napotkasz problemu, to rozwiązanie jest w porządku, jak powiedziałem. Ale dziękuję za niepotrzebne głosy przeciw @syntaxerror. To rozwiązanie zadziała dla niektórych, jak pokaże (obecnie) 19 głosów za, ale jeśli nie, nie używaj go do swojego rozwiązania. Istnieje wiele sposobów rozwiązania problemu PO.
Ascherer,
1
Jeśli używasz awk w wierszu poleceń w swojej codziennej pracy, jest to zdecydowanie rozwiązanie, którego potrzebujesz. Czy to nie jest oczywiste? Sprawdzanie błędów itp. Nie ma w tym przypadku większego znaczenia, ponieważ wpisujesz go i możesz wyłapać tego typu rzeczy przed naciśnięciem klawisza Enter (osobiście nie sądzę, aby awk i tak było używane do niczego innego, dlatego Mam perl, python, tcl i około 100+ innych, lepszych, szybszych, mniej irytujących języków skryptowych!) Oczywiście, może daję moim kolegom programistom zbyt duży kredyt i naprawdę potrzebują sprawdzania błędów nawet w tym, co piszą w locie (??)
osirisgothra
11
sed -re 's,\s+, ,g' | cut -d ' ' -f 9-

Zamiast zajmować się białymi znakami o zmiennej szerokości, zamień wszystkie białe znaki na pojedynczą spację. Następnie użyj prostego cutz interesującymi polami.

Nie używa awk, więc nie jest normalne, ale wydaje się odpowiednie, biorąc pod uwagę inne odpowiedzi / komentarze.

Jakiś głupiec
źródło
1
Podaj dokładniejszą odpowiedź, w przeciwnym razie opublikuj to jako komentarz do pytania.
Alper Turan
Jest to idealne do ps faux | użycia. Nigdy nie bój się przyznać, że narzędzie XYZ nie jest najwłaściwsze.
kevinf
10

Ogólnie perl zastępuje awk / sed / grep et. al., i jest znacznie bardziej przenośny (a także po prostu lepszy scyzoryk).

perl -lane 'print "@F[8..$#F]"'

Oczywiście obowiązuje Timtowtdi.

bobbogo
źródło
Musisz dodać opcję wiersza poleceń -llub dodać \ndo instrukcji print.
glenn jackman
@glenn jackman: Prawdopodobnie. Nie jest wymagane, jeśli jest częścią innej wiadomości, lub jest przypisane do zmiennej itp. Jeśli chodzi o „lepsze”, perl z pewnością wygląda lepiej w small. Trzeba przyznać, że może wyglądać bardzo nieporządnie.
bobbogo
Nie zrozum mnie źle, lubię Perla. Uwielbiam awk za to, czym jest.
glenn jackman
Moje urządzenie osadzone nie jest dostarczane z Perlem, ale ma awk.
Sepero
Głosowanie w dół, ponieważ pytanie dotyczyło tego, jak to zrobić w awk, a nie w perl, ruby, java, python, bash.
Tom Harrison,
3
awk -v m="\x01" -v N="3" '{$N=m$N ;print substr($0, index($0,m)+1)}'

To odcina to, co jest 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ą Ascherera.

Zdefiniuj funkcję:

fromField () { 
awk -v m="\x01" -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   

Wyjście zachowuje wszystko, łącznie ze spacjami końcowymi. Dla N = 0 zwraca cały wiersz taki, jaki jest, a dla n> NF pusty łańcuch

Robert Vila
źródło
To jest dobry pomysł. Nie działa to całkiem na obecnym Macu używającym typowego gawk, ponieważ załamuje się $ 0. Rozwiązaniem jest ustawienie zmiennej na $ 0 w pierwszym kroku, na przykład: '{s = $ 0; ... print substr (s, index (s, m) +1}
joelparkerhenderson
1

Oto przykład ls -lwyniku:

-rwxr-----@ 1 ricky.john  1493847943   5610048 Apr 16 14:09 00-Welcome.mp4
-rwxr-----@ 1 ricky.john  1493847943  27862521 Apr 16 14:09 01-Hello World.mp4
-rwxr-----@ 1 ricky.john  1493847943  21262056 Apr 16 14:09 02-Typical Go Directory Structure.mp4
-rwxr-----@ 1 ricky.john  1493847943  10627144 Apr 16 14:09 03-Where to Get Help.mp4

Moje rozwiązanie do druku cokolwiek postu $9jestawk '{print substr($0, 61, 50)}'

rickydj
źródło
0
ruby -lane 'print $F[3..-1].join(" ")' file
kurumi
źródło
0

Aby wyświetlić pierwsze 3 pola i wydrukować pozostałe pola, możesz użyć:

awk '{s = ""; for (i=4; i<= NF; i++) s= s $i : "; print $1 $2 $3 s}' filename

gdzie 1 $ 2 $ 3 to pierwsze 3 pola.

Raymond C. Borges Hink
źródło
0
function print_fields(field_num1, field_num2){
    input_line = $0

    j = 1;
    for (i=field_num1; i <= field_num2; i++){
        $(j++) = $(i);

    }
    NF = field_num2 - field_num1 + 1;
    print $0

    $0 = input_line
}
msol01
źródło
0

Używanie cut zamiast awk i przezwyciężanie problemów z ustalaniem, od której kolumny zacząć, za pomocą polecenia -c znak cut.

Tutaj mówię, podaj mi wszystkie oprócz pierwszych 49 znaków wyniku.

 ls -l /some/path/*/* | cut -c 50-

Na /*/*/końcu polecenia ls mówi, że pokaż mi, co jest również w podkatalogach.

Możesz także wyciągnąć pewne zakresy znaków ala (z wyciętej strony podręcznika). Np. Pokaż nazwy i czasy logowania aktualnie zalogowanych użytkowników:

       who | cut -c 1-16,26-38
Joe
źródło