@MaxMackie askubuntu.com/questions/88142/… . O tej porze nie mogę dostać modu, więc zgłosiłem go, prosząc o migrację, jeśli chcą; ma już zaakceptowaną odpowiedź, więc nie jestem pewien, czy to zrobią
Michał Mrożek
@MichaelMrozek, hmmm co zwykle dzieje się w takich sytuacjach? Czy po prostu przechowujemy duplikaty?
Oprócz tego, jak wycinać i ponownie układać pola (omówione w innych odpowiedziach), istnieje problem dziwnych pól CSV.
Jeśli Twoje dane należą do tej „dziwacznej” kategorii, możesz zająć się tym trochę wstępnego i końcowego filtrowania. Filtry przedstawione poniżej wymagają znaki \x01, \x02, \x03, \x04aby nie pojawia się nigdzie w swoich danych.
Oto filtry owinięte wokół prostego awkzrzutu pola.
Uwaga: pole pięć ma niepoprawny / niekompletny układ „pola cytowanego”, ale jest łagodny na końcu wiersza (w zależności od parsera CSV). Ale, oczywiście, spowodowałoby to problematyczne nieużywane wyniki, gdyby miał zostać zamieniony z bieżącej pozycji na końcu rzędu .
Aktualizacja; użytkownik121196 wskazał błąd, gdy przecinek poprzedza końcowy cytat. Oto poprawka.
Dane
cat <<'EOF'>file
field one,"fie,ld,two",field"three","field,\",four","field,five
"15111 N. Hayden Rd., Ste 160,",""
EOF
field one
"fie,ld,two"
field"three""field,\",four""field,five
"15111 N. Hayden Rd., Ste 160,"""
Oto filtr wstępny , rozszerzony o komentarze. Filtr po to tylko odwrócenie . , , \x01\x02\x03\x04
sed -r '
s/^/,/# add a leading comma delimiter
s/\\"/\x01/g # obfuscate escaped quotation-mark (\")
s/,"([^"]*)"/,\x02\1\x03/g # obfuscate quotation-marks
s/,"/,\x02/# when no trailing quote on last field :MC # obfuscate commas embedded in quotes
s/\x02([^\x03]*),([^\x03]*)/\x02\1\x04\2/g
tMC
s/^,// # remove spurious leading delimiter'
@ user121196 - Jak wspomniano w zdaniu otwierającym, ta odpowiedź pokazuje sposób na zwiększenie spójności danych CSV. np. zastępując tymczasowo przecinek umieszczony w cudzysłowie neutralnym znakiem tokena ... a następnie przenosząc go z powrotem do przecinka po przeniesieniu / wycięciu / usunięciu. Ponownie, jak wspomniano, krok przenoszenia / wycinania / usuwania jest zastępowany zwykłym zrzutem pola awk .
Peter.O
1
nie udaje się w tym przypadku: „15111 N. Hayden Rd., Ste 160,”, „”
121196
@ user121196: Dziękujemy za zwrócenie na to uwagi. Zaktualizowałem odpowiedź z poprawką.
Peter.O,
15
Zależy to od tego, czy plik CSV używa przecinków tylko do ograniczników, czy też masz szaleństwo, takie jak:
pole pierwsze, „pole dwa”, pole trzecie
Zakłada się, że używasz prostego pliku CSV:
Usuwanie kolumny
Możesz pozbyć się jednej kolumny na wiele sposobów; Jako przykład użyłem kolumny 2. Najłatwiejszym sposobem jest prawdopodobnie użycie cut, które pozwala określić ogranicznik -di które pola chcesz wydrukować -f; nakazuje to podział na przecinki i pole wyjściowe 1, a pola 3 do końca:
$ cut -d,-f1,3-/path/to/your/file
Jeśli faktycznie potrzebujesz użyć sed, możesz napisać wyrażenie regularne pasujące do pierwszych n-1pól, pola nth i reszty, i pomiń wypisywanie nth (tutaj njest 2, więc pierwsza grupa dopasowuje 1czas :) \{1\}:
$ sed 's/\(\([^,]\+,\)\{1\}\)[^,]\+,\(.*\)/\1\3/'/path/to/your/file
Istnieje wiele sposobów, aby to zrobić awk, żaden z nich nie jest szczególnie elegancki. Możesz użyć forpętli, ale radzenie sobie z przecinkiem końcowym jest uciążliwe; ignorując, że byłoby to coś takiego:
Ponieważ jest to CSV, będziesz także potrzebować BEGIN { FS=","; OFS=","; }.
1
Myślę, że nawet FS = OFS = "," zadziała.
5
Biorąc pod uwagę plik rozdzielany spacjami w następującym formacie:
12345
Możesz usunąć pole 2 za pomocą awk tak:
awk '{ sub($2,""); print}' file
który zwraca
1345
W razie potrzeby zastąp kolumnę 2 kolumną n.
Aby powielić kolumnę 2,
awk '{ col = $2 " " $2; $2 = col; print }' file
który zwraca
122345
Aby przełączyć kolumny 2 i 3,
awk '{temp = $2; $2 = $3; $3 = temp; print}'
który zwraca
13245
awk jest ogólnie bardzo dobry w radzeniu sobie z koncepcją pól . Jeśli masz do czynienia z plikiem CSV, a nie plikiem rozdzielanym spacjami, możesz po prostu użyć
awk -F,
aby zdefiniować pole jako przecinek zamiast spacji (która jest domyślna). Istnieje wiele dobrych zasobów awk online, z których jeden wymieniłem jako źródło poniżej.
Niewiele wiem o tym awk, ale wydaje się, że generuje separację spacji, nawet jeśli separator pól jest ,(separator pól kontroluje tylko sposób, w jaki obsługuje dane wejściowe)
Michał Mrożek
@MichaelMrozek: tak, to zmienna aws OFS, która kontroluje separator pól wyjściowych.
enzotib
Tak, i jak wspomniałem w mojej odpowiedzi, możesz przekazać opcję -F, aby awk zmienić separator (np. -F,)
Odpowiedzi:
Oprócz tego, jak wycinać i ponownie układać pola (omówione w innych odpowiedziach), istnieje problem dziwnych pól CSV.
Jeśli Twoje dane należą do tej „dziwacznej” kategorii, możesz zająć się tym trochę wstępnego i końcowego filtrowania. Filtry przedstawione poniżej wymagają znaki
\x01
,\x02
,\x03
,\x04
aby nie pojawia się nigdzie w swoich danych.Oto filtry owinięte wokół prostego
awk
zrzutu pola.Uwaga: pole pięć ma niepoprawny / niekompletny układ „pola cytowanego”, ale jest łagodny na końcu wiersza (w zależności od parsera CSV). Ale, oczywiście, spowodowałoby to problematyczne nieużywane wyniki, gdyby miał zostać zamieniony z bieżącej pozycji na końcu rzędu .
Aktualizacja; użytkownik121196 wskazał błąd, gdy przecinek poprzedza końcowy cytat. Oto poprawka.
Dane
Kod
Wyjście:
Oto filtr wstępny , rozszerzony o komentarze. Filtr po to tylko odwrócenie . , ,
\x01
\x02
\x03
\x04
źródło
Zależy to od tego, czy plik CSV używa przecinków tylko do ograniczników, czy też masz szaleństwo, takie jak:
Zakłada się, że używasz prostego pliku CSV:
Usuwanie kolumny
Możesz pozbyć się jednej kolumny na wiele sposobów; Jako przykład użyłem kolumny 2. Najłatwiejszym sposobem jest prawdopodobnie użycie
cut
, które pozwala określić ogranicznik-d
i które pola chcesz wydrukować-f
; nakazuje to podział na przecinki i pole wyjściowe 1, a pola 3 do końca:Jeśli faktycznie potrzebujesz użyć
sed
, możesz napisać wyrażenie regularne pasujące do pierwszychn-1
pól, polan
th i reszty, i pomiń wypisywanien
th (tutajn
jest 2, więc pierwsza grupa dopasowuje1
czas :)\{1\}
:Istnieje wiele sposobów, aby to zrobić
awk
, żaden z nich nie jest szczególnie elegancki. Możesz użyćfor
pętli, ale radzenie sobie z przecinkiem końcowym jest uciążliwe; ignorując, że byłoby to coś takiego:Uważam, że łatwiej jest wyprowadzić pole 1, a następnie użyć
substr
do wyciągnięcia wszystkiego po polu 2:Jest to denerwujące dla kolumn dalej
Duplikowanie kolumny
W
sed
ten jest zasadniczo taki sam wyraz twarzy jak poprzednio, ale także przechwytywać kolumnę docelową i uwzględnić tę grupę wielokrotnie w wymianie:W
awk
przypadku pętli for byłoby to coś w stylu (ponownie ignorując przecinek końcowy):substr
Sposób:(tcdyl wymyślił lepszą metodę w swojej odpowiedzi )
Przenoszenie kolumny
Myślę, że
sed
rozwiązanie wynika naturalnie z pozostałych, ale zaczyna robić się absurdalnie długieźródło
awk
to twój najlepszy zakład.awk
drukuje pola według numeru, więc ...Aby usunąć kolumnę, nie drukuj jej:
Aby zmienić kolejność:
Przekieruj do pliku wyjściowego.
awk
może również sformatować dane wyjściowe.Wyjście w formacie awk
źródło
BEGIN { FS=","; OFS=","; }
.Biorąc pod uwagę plik rozdzielany spacjami w następującym formacie:
Możesz usunąć pole 2 za pomocą awk tak:
który zwraca
W razie potrzeby zastąp kolumnę 2 kolumną n.
Aby powielić kolumnę 2,
który zwraca
Aby przełączyć kolumny 2 i 3,
który zwraca
awk jest ogólnie bardzo dobry w radzeniu sobie z koncepcją pól . Jeśli masz do czynienia z plikiem CSV, a nie plikiem rozdzielanym spacjami, możesz po prostu użyć
aby zdefiniować pole jako przecinek zamiast spacji (która jest domyślna). Istnieje wiele dobrych zasobów awk online, z których jeden wymieniłem jako źródło poniżej.
Źródło dla # 3
źródło
awk
, ale wydaje się, że generuje separację spacji, nawet jeśli separator pól jest,
(separator pól kontroluje tylko sposób, w jaki obsługuje dane wejściowe)Będzie to działać w przypadku usuwania
Wkład
Wydajność
źródło