Verbinden Sie mehrere sed-Befehle in einem Skript, um die CSV-Datei zu verarbeiten

34

Eine CSV-Datei wie diese haben:

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

und auf der Suche nach Ergebnis wie:

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

mit anderen Worten: Entfernen von "FOOTER", Anführungszeichen am Anfang, Ende und um |.

Bisher funktioniert dieser Code:

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

Wie Sie sehen, werden 4 zusätzliche Dateien erstellt.

Hier ist eine andere Lösung, die das Ziel hat, keine zusätzlichen Dateien zu erstellen und dasselbe in einem einzigen Skript zu tun. Das funktioniert nicht sehr gut.

#!/bin/ksh

sed '/begin/, /end/ { 
        /FOOTER/d
        s/^\"//
        s/\"$//
        s/\"|\"/|/g 
}' csv > csv4
Bor
quelle
1
Da Sie Anführungszeichen haben, können Sie Zeilenumbrüche in den Feldern haben. du sedwirst damit nicht arbeiten, nur mit vereinfachtem csv. Verwenden Sie eine Programmiersprache mit einer Bibliothek, die echte CSV-Dateien verarbeiten kann (Python / Perl / Ruby).
Anthon

Antworten:

44

Erstens, wie Michael gezeigt hat, können Sie all diese Befehle einfach zu einem einzigen Befehl kombinieren:

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

Ich denke, einige sedImplementierungen kommen damit nicht klar und benötigen möglicherweise:

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

Das heißt, es sieht so aus, als wären Ihre Felder durch definiert, |und Sie möchten nur "das gesamte Feld entfernen und die Felder im Feld belassen. In diesem Fall können Sie Folgendes tun:

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

Oder mit GNU sed:

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

Sie könnten auch Perl verwenden:

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

Das würde auch funktionieren:

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

Beispiel:

$ 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"

hübsche Version

sed '
s/^"//
s/"|"/|/g
s/""$/"/
$d
'
Michael Durrant
quelle
1
Dies betrifft nicht die Fußzeile.
Terdon
3
Dadurch wird jedoch die letzte Zeile unabhängig vom Inhalt entfernt. Wenn dies nicht der Fall ist FOOTER, werden die gewünschten Daten entfernt.
terdon