Czy istnieje zaklęcie wiersza polecenia, aby upuścić kolumnę w pliku CSV?

32

Posiadające plik o następującej treści:

1111,2222,3333,4444
aaaa,bbbb,cccc,dddd

Próbuję uzyskać plik równy oryginałowi, ale nie ma n-tej kolumny, np. Dla n = 2 (lub może to być 3)

1111,2222,4444
aaaa,bbbb,dddd

lub, dla n = 0 (lub może to być 1)

2222,3333,4444
bbbb,cccc,dddd

Rzeczywistym plikiem może być gigabajt długości kilkudziesięciu tysięcy kolumn.

Jak zawsze w takich przypadkach, podejrzewam, że magicy z linii poleceń mogą zaoferować eleganckie rozwiązanie ... :-)

W moim prawdziwym przypadku muszę upuścić 2 pierwsze kolumny, co można zrobić, upuszczając pierwszą kolumnę dwa razy w sekwencji, ale przypuszczam, że bardziej interesujące byłoby uogólnienie nieco.

Ivan
źródło
Czy pola nie mogą zawierać ,? (Tj. ,Służy tylko jako separator pól).
CVn
@ MichaelKjörling, byłoby miło mieć bardziej elastyczne rozwiązanie, ale w moim przypadku - tak: separator jest ,i nigdy nie występuje wewnątrz pola.
Ivan
W takim przypadku odpowiedź Scotta powinna być właśnie taka.
CVn

Odpowiedzi:

47

Uważam, że jest to specyficzne dla wycięcia z podstawowych GNU:

$ cut --complement -f 3 -d, inputfile
1111,2222,4444
aaaa,bbbb,dddd

Zazwyczaj określasz pola, które chcesz, poprzez -f, ale dodając - dopełnij, naturalnie odwracasz znaczenie. Z „man cut”:

--complement
    complement the set of selected bytes, characters or fields

Jedno zastrzeżenie: jeśli którakolwiek z kolumn zawiera przecinek, zostanie odcięta, ponieważ wycięcie nie jest parserem CSV w taki sam sposób, jak arkusz kalkulacyjny. Wiele parserów ma różne pomysły na temat obsługi przecinków w CSV. W prostym przypadku CSV, w wierszu poleceń cięcie jest wciąż właściwą drogą.

Scott McClung
źródło
4
To działa dobrze, o ile jest to prosty plik CSV. Jeśli którakolwiek z kolumn jest ciągiem z przecinkiem, zostanie odrzucona cut, ponieważ nie jest parserem CSV. Jeśli pole CSV ma w swojej wartości separator pól, jest ono zawinięte w cudzysłów. Btw, na temat cut, -fodbywa zakresy pól. cut -f, -d3-wypisze trzecie pole na, usuwając pierwsze dwa.
Alexios
2
Masz na myślicut -d, -f3-
Bezużyteczny
@Alexios to dobry punkt. Nigdy tak naprawdę nie mam do czynienia z „prawdziwym” CSV, tylko z prostym podzbiorem. Zmienię swoją odpowiedź, aby to odzwierciedlić.
Scott McClung
@Useless: Cholera, tak. To właśnie nazywam moją „ciętą dysleksją” uderzającą ponownie. westchnienie . Scott: Pliki CSV to podstępne bestie. Zbyt wiele różnych pod-formatów, z których niektóre nie są nawet C SV, ale i tak są konwencjonalnie nazywane.
Alexios
Spowoduje to wydrukowanie nowego pliku CSV na moim terminalu - w jaki sposób mogę go zastąpić (lub może napisać do nowego pliku, wygląda na to, że OP go szukał)?
Max Ghenis,
12

Jeśli dane są po prostu wykonane z kolumn oddzielonych przecinkami:

cut -d , -f 1-2,4-

Możesz także użyć awk, ale jest to trochę niewygodne, ponieważ usuwanie pola jest łatwe, ale usuwanie separatora zajmuje trochę pracy. Jeśli nie masz pustego pola, nie jest tak źle:

awk -F , 'BEGIN {OFS=FS}  {$3=""; sub(",,", ","); print}'

Jeśli masz rzeczywisty plik CSV, w którym przecinki mogą pojawiać się w polach, jeśli są odpowiednio cytowane, potrzebujesz prawdziwej biblioteki CSV .

Gilles „SO- przestań być zły”
źródło