Drukuj kolumny w awk według nazwy nagłówka

12

Mam taki plik tekstowy

foo bar baz
1   a   alpha
2   b   beta
3   c   gamma

Mogę użyć awk do wydrukowania niektórych kolumn, takich jak 1 i 3, {print $1, $3}ale chcę określić kolumny do wydrukowania, podając zamiast tego nagłówek kolumny, coś w rodzaju {print $foo, $baz}. Jest to przydatne, więc nie muszę otwierać pliku i ręcznie zliczać kolumn, aby zobaczyć, która kolumna jest, i nie muszę aktualizować skryptu, jeśli zmieni się numer kolumny lub kolejność. Czy mogę to zrobić za pomocą awk (lub innego narzędzia powłoki)?

użytkownik1350864
źródło

Odpowiedzi:

17
awk '
NR==1 {
    for (i=1; i<=NF; i++) {
        f[$i] = i
    }
}
{ print $(f["foo"]), $(f["baz"]) }
' file
foo baz
1 alpha
2 beta
3 gamma

To niezwykle użyteczny idiom. Mam wiele danych w arkuszach kalkulacyjnych i różne arkusze kalkulacyjne mogą mieć wspólny podzbiór kolumn, którymi jestem zainteresowany, ale niekoniecznie w tej samej kolejności we wszystkich arkuszach kalkulacyjnych lub z taką samą liczbą innych kolumn przed / między nimi, aby móc eksportować jako CSV lub podobny, a następnie po prostu uruchom skrypt awk, używając nazw kolumn zamiast numerów kolumn, jest absolutnie nieoceniony.

Ed Morton
źródło
To wielkie dzięki i działa dla moich celów. Czy jesteś w stanie wyjaśnić, jak to działa dla początkujących awk? Co robi w tym składnia f [$ i] i jak awk sprawdza, które kolumny pasują do łańcuchów?
AlexLipp
Nie ma za co. To absolutnie podstawowa składnia awk, wystarczy wyszukać pola i tablice na stronie podręcznika awk (lub google go). Dodaj print ii print $ii print f [$ i] `oświadczenia w pętli, itd., Aby co dzieje czy to pomaga śladowe.
Ed Morton
1

Prosić awk, ale można też użyć bardziej wyspecjalizowanym narzędziem do tego: csvtool.

csvtool -t ' ' -u ' ' namedcol foo,baz file

lub

csvtool -t ' ' -u ' ' col 1,3 file
pLumo
źródło
1

Zakładając, że plik jest plikiem TSV („wartości rozdzielane tabulatorami”), przy użyciu csvkit:

$ csvcut -t -c foo,baz file.tsv
foo,baz
1,alpha
2,beta
3,gamma

Dane wyjściowe zostaną poprawnie sformatowane CSV, ale można je łatwo zmienić z powrotem na TSV:

$ csvcut -t -c foo,baz file.tsv | csvformat -T
foo     baz
1       alpha
2       beta
3       gamma

-cOpcja csvcutmoże mieć również numery i zakresy, a także może być używany do przestawiać kolumny danych wejściowych (funkcja często brakuje w standardowym cutUtility).

Kusalananda
źródło