Połącz wiele poleceń sed w jednym skrypcie do przetwarzania pliku CSV

34

Posiadanie pliku CSV takiego:

HEADER
"first, column"|"second "some random quotes" column"|"third ol' column"
FOOTER

i szukam wyników takich jak:

HEADER
first, column|second "some random quotes" column|third ol' column

innymi słowy, usuwając „FOOTER”, cytaty na początku, na końcu i wokół |

Do tej pory ten kod działa:

sed '/FOOTER/d' csv > csv1 | #remove FOOTER
sed 's/^\"//' csv1 > csv2 | #remove quote at the beginning
sed 's/\"$//' csv2 > csv3 | #remove quote at the end
sed 's/\"|\"/|/g' csv3 > csv4 #remove quotes around pipe

Jak widzisz problem polega na tym, że tworzy 4 dodatkowe pliki.

Oto inne rozwiązanie, którego celem jest nie tworzenie dodatkowych plików i robienie tego samego w jednym skrypcie. To nie działa zbyt dobrze.

#!/bin/ksh

sed '/begin/, /end/ { 
        /FOOTER/d
        s/^\"//
        s/\"$//
        s/\"|\"/|/g 
}' csv > csv4
Bor
źródło
1
Ponieważ masz cytaty, możesz mieć nowe wiersze w polach. Twój sednie będzie działać z tym, tylko z uproszczonej csv. Użyj języka programowania z biblioteką, która może obsługiwać prawdziwe pliki CSV (Python / Perl / Ruby).
Anthon

Odpowiedzi:

44

Po pierwsze, jak pokazał Michael, możesz po prostu połączyć je wszystkie w jedno polecenie:

sed '/^FOOTER/d; s/^\"//; s/\"$//; s/\"|\"/|/g' csv > csv1

Myślę, że niektóre sedimplementacje nie mogą sobie z tym poradzić i mogą wymagać:

  sed -e '/^FOOTER/d' -e 's/^\"//' -e 's/\"$//' -e 's/\"|\"/|/g' csv > csv1

To powiedziawszy, wygląda na to, że twoje pola są zdefiniowane przez |i chcesz po prostu usunąć "całe pole, pozostawiając te, które są w polu. W takim przypadku możesz wykonać:

$ sed '/FOOTER/d; s/\(^\||\)"/\1/g; s/"\($\||\)/\1/g' csv 
HEADER
first, column|second "some random quotes" column|third ol' column

Lub z GNU sed:

sed -r '/FOOTER/d; s/(^|\|)"/\1/g; s/"($|\|)/\1/g' csv 

Możesz także użyć Perla:

$ perl -F"|" -lane 'next if /FOOTER/; s/^"|"$// for @F; print @F' csv 
HEADER
first, column|second some random quotes column|third ol' column
terdon
źródło
13

Działa to również:

sed 's / ^ "//; s /" | "/ | / g; s /" "$ /" /'

Przykład:

$ echo '"this"|" and "ths""|" and "|" this 2"|" also "this", "thi", "and th""' | 
sed 's/^"//; s/"|"/|/g; s/""$/"/'
this| and "ths"| and | this 2| also "this", "thi", "and th"

ładna wersja

sed '
s/^"//
s/"|"/|/g
s/""$/"/
$d
'
Michael Durrant
źródło
1
To nie dotyczy stopki.
terdon
3
Ale to usunie ostatni wiersz bez względu na jego zawartość. Jeśli nie FOOTER, usunie poszukiwane dane.
terdon