2013-08-27 20 views
14

Załóżmy, że mamy ten plik danych.wydrukuj resztę pól w awk

john 32 maketing executive 
jack 41 chief technical officer 
jim 27 developer 
dela 33 assistant risk management officer 

Chcę drukować przy użyciu awk

john maketing executive 
jack chief technical officer 
jim developer 
dela assistant risk management officer 

wiem, można to zrobić za pomocą for.

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

Problem jest długi i wygląda na skomplikowany.

Czy jest inny krótki sposób drukowania reszty pól.

+0

Prostym hackiem jest ustawienie $ 2 na "", a następnie wydrukowanie 0 USD (wszystkie pola) - jednak dałoby to dodatkowy ogranicznik pustego pola. – mkfs

+0

Trzy lata później pomogłeś mi. Ale powinieneś zmienić " Koreth

Odpowiedz

28

Ustaw pole (y) chcesz, aby pominąć puste:

awk '{$2 = ""; print $0;}' < file_name 

Źródło: Using awk to print all columns from the nth to the last

+2

Nie czyści dodatkowej przestrzeni i używa niepotrzebnego 'print $ 0', który może być zastąpiony prostym' 1' – Jotne

+0

@Jotne Kiedy używam '1' na miejscu' print $ 0', nie otrzymuję żadnych danych wyjściowych z awk. Jesteś pewien, że są one równoważne? – Alex

+0

nie działało dla pominięcia pierwszego pustego bloku – malhal

3

Można użyć prostego awk tak:

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

Jednak będzie to miało dodatkowe OFS na wyjściu, którego można uniknąć dzięki temu awk

awk '{sub($2 OFS, "")}1' file 

albo za pomocą tej tr i pokroić combo:

W systemie Linux:

tr -s ' ' < file | cut -d ' ' -f1,f3- 

Na OSX:

tr -s ' ' < file | cut -d ' ' -f1 -f3- 
+0

Powinno to być 'cut -d '' -f1,3-'. –

+0

@ AdrianFrühwirth: Dzięki, ale 'cut -f1,3-' nie jest przenośny i nie jest obsługiwany przez mój OSX. – anubhava

+0

Następnie OSX 'cut' jest zepsuty. [POSIX] (http://pubs.opengroup.org/onlinepubs/007904975/utilities/cut.html) mówi, że * Aplikacja powinna zapewnić, że lista argumentów opcji (patrz opcje -b, -c i -f poniżej) jest listą rozdzielaną przecinkami [...] * i '-f -f' łamie na moim Linuxie z' coreutils-8.16' z komunikatem o błędzie * cut: można podać tylko jeden typ listy *. –

4

usuwa złożony # 2 i czyści dodatkowa przestrzeń.

awk '{$2="";sub(" "," ")}1' file 
+0

co robi ten dodatkowy "1" tutaj? –

+2

@ shiplu.mokadd.im Wartość '1' określa wartość true, która kopie w bloku domyślnym (' {print $ 0} '). –

+0

Nic nie czyści, ale zamiast tego, jak wszystkie przepisz istniejące pola - zastępuje 'IFS' (jeden lub więcej z rzędu) w pojedynczy' OFS'. Na przykład. to jeden ze sposobów zaimplementowania filtru "normalizuj spacje": 'awk '{1 $ = 1 $} 1'' –

2

Innym sposobem jest po prostu użyć sed do zastąpienia pierwsze cyfry i przestrzeni mecz:

sed 's|[0-9]\+\s\+||' file

8

niezawodnie awk GNU dla gensub() przy użyciu domyślnego FS:

$ gawk -v delNr=2 '{$0=gensub("^([[:space:]]*([^[:space:]]+[[:space:]]+){"delNr-1"})[^[:space:]]+[[:space:]]*","\\1","")}1' file 
john maketing executive 
jack chief technical officer 
jim developer 
dela assistant risk management officer 

Z innymi awariami, musisz użyć match() i substr() zamiast gensub(). Zauważ, że zmienna delNr powyżej mówi awk które pole chcesz usunąć:

$ gawk -v delNr=3 '{$0=gensub("^([[:space:]]*([^[:space:]]+[[:space:]]+){"delNr-1"})[^[:space:]]+[[:space:]]*","\\1","")}1' file 
john 32 executive 
jack 41 technical officer 
jim 27 
dela 33 risk management officer 

Nie rób tego:

awk '{sub($2 OFS, "")}1' 

jako ten sam tekst, który znajduje się w $ 2 Klienci być na końcu $ 1, a/lub 2 $ może zawierać metaznaki RE, więc istnieje bardzo duża szansa, że ​​usuniesz niewłaściwy ciąg w ten sposób.

nie rób tego:

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

gdyż dodaje FS i skompresować wszystkie inne ciągłą białą przestrzeń pomiędzy polami w jednym pustym char każdego.

nie rób tego:

awk '{$2="";sub(" "," ")}1' file 

gdyż hasthe problem przestrzeń kompresji wymienione powyżej i opiera się na twardej kodowane FS pojedynczego wykroju (domyślnie, choć, więc może nie jest tak źle), ale co ważniejsze, jeśli były spacje przed 1 $, usunąłby jeden z tych miejsc zamiast miejsca, w którym dodaje 1 do 2 USD.

Ostatnią rzeczą wartą wspomnienia jest to, że w najnowszych wersjach gawk jest nowa funkcja patsplit(), która działa jak split() ALE oprócz tworzenia tablicy pól, tworzy także tablicę przestrzeni między polami. Oznacza to, że możesz manipulować polami i spacjami pomiędzy nimi w tablicach, aby nie martwić się, że awk rekompiluje rekord używając OFS, jeśli manipulujesz polem. Następnie wystarczy wydrukować żądane pola z tablic. Zobacz patsplit() w http://www.gnu.org/software/gawk/manual/gawk.html#String-Functions, aby uzyskać więcej informacji.

+1

ta odpowiedź nie jest szybka i brudna, ale człowiek może się z niej uczyć. +1 dla informacji. – Kent

+0

Patrząc na te komplikacje można się zastanawiać, czy awk jest rzeczywiście najlepszym narzędziem do tej pracy. na przykład jeśli pola są rozdzielane przecinkami lub przecinkami, cały kod awk musi zostać przepisany. – anubhava

+0

Zależy od wprowadzonych danych. Jeśli masz pojedyncze znaki między polami, wtedy 'cut' jest lepszy. Jeśli masz coś jeszcze, to gawk + gensub() lub sed (bardzo podobne syntaktycznie) mogą być najlepszymi opcjami. Oba mogą napotkać problemy podczas próby opisania negacji wielorakich RE, więc musisz spojrzeć na gawk + patsplit() lub gawk + FPAT. Niestety, nie ma srebrnej kuli. –