Ich habe eine Eingabedatei, die durch Kommas ( ,
) getrennt ist. In Anführungszeichen eingeschlossene Felder enthalten ein Komma. Hier ist die Beispielzeile
123,"ABC, DEV 23",345,534.202,NAME
Ich muss alle Kommas entfernen, die in den doppelten Anführungszeichen und den doppelten Anführungszeichen vorkommen. Daher sollte die obige Zeile wie unten gezeigt analysiert werden
123,ABC DEV 23,345,534.202,NAME
Ich habe Folgendes versucht, sed
aber nicht die erwarteten Ergebnisse erzielt.
sed -e 's/\(".*\),\(".*\)/\1 \2/g'
Jeder schneller Trick mit sed
, awk
oder jedes anderes Unix - Dienstprogramm bitte?
text-processing
sed
awk
csv
mtk
quelle
quelle
Antworten:
Wenn die Anführungszeichen ausgeglichen sind, möchten Sie die Kommas zwischen den anderen Anführungszeichen entfernen. Dies kann folgendermaßen ausgedrückt werden
awk
:Ausgabe:
Erläuterung
Das
-F"
Kommando awk trennt die Zeile an den doppelten Anführungszeichen, was bedeutet, dass jedes zweite Feld der Text zwischen den Anführungszeichen ist. Die for-Schleifegsub
, kurz für global substitute, wird in jedem anderen Feld ausgeführt und ersetzt comma (","
) durch nothing (""
). Der1
am Ende ruft den Standard - Code-Block:{ print $0 }
.quelle
gsub
kurz erläutern, wie dieser eine Liner funktioniert? Bitte.{ print $0 }
. Das habe ich auch zur Erklärung hinzugefügt.prefix,"something,otherthing[newline]something , else[newline]3rdline,and,things",suffix
innerhalb eines mehrzeiligen doppelt zitieren mehrere Linien und verschachtelt „“ überall: der gesamte (dh"...."
Teil versetzte werden soll , und im Innern,
sollte ersetzt / entfernt ...): In diesem Fall werden in Ihrem Skript keine doppelten Anführungszeichen angezeigt, und die Lösung ist nicht einfach. doppelte Anführungszeichen ... +\"
awk -F'"' -v OFS='"' '{ for (I=1; i<=NF; i+=2) gsub(",", "|", $i) } 1' infile
Es gibt eine gute Antwort, wenn sed einfach einmal mit einer Schleife verwendet wird :
Erläuterung:
:a;
ist ein Label für Furter Branchs/^\(\([^"]*,\?\|"[^",]*",\?\)*"[^",]*\),/\1 /
könnte 3 beiliegende Teile enthalten[^"]*,\?\|"[^",]*",\?
Übereinstimmung für eine Zeichenfolge ohne Anführungszeichen, möglicherweise gefolgt von einem Koma oder einer Zeichenfolge, die von zwei Anführungszeichen ohne Koma und möglicherweise gefolgt von einem Koma eingeschlossen ist.ta
führt eine Schleife durch,:a
wenn sich der vorheriges/
Befehl geändert hat.quelle
Eine allgemeine Lösung, die auch mehrere Kommas zwischen ausgeglichenen Anführungszeichen verarbeiten kann, erfordert eine verschachtelte Ersetzung. Ich implementiere eine Lösung in Perl, die jede Zeile einer bestimmten Eingabe verarbeitet und in jedem anderen Paar von Anführungszeichen nur Kommas ersetzt:
oder kurz gesagt
Sie können entweder den zu verarbeitenden Text an den Befehl weiterleiten oder die zu verarbeitende Textdatei als letztes Befehlszeilenargument angeben.
quelle
[^\\]
wird den unerwünschten Effekt haben , der das letzte Zeichen innerhalb der Anführungszeichen passend und es (nicht \ Zeichen) entfernen, das heißt, sollten Sie verbrauchen nicht diesen Charakter. Versuchen Sie es(?<!\\)
stattdessen.[^"]*
das Spiel nicht gierig zu machen (dh passt alles von einem"
zum nächsten"
):perl -pe 's/"([^"]+)"/($match = $1) =~ (s:,::g);$match;/ge;'
. Es erkennt nicht die ausgefallene Idee, dass ein Zitat mit einem Backslash entkommen könnte :-)[^"]*
Ansatz oder der explizite nicht-gierige Ansatz weniger CPU-Zeit verbraucht.Ich würde eine Sprache mit einem richtigen CSV-Parser verwenden. Beispielsweise:
quelle
Ihre zweiten Anführungszeichen sind falsch:
Die Verwendung von regulären Ausdrücken entspricht außerdem in der Regel dem längsten Teil des Texts. Dies bedeutet, dass dies nicht funktioniert, wenn Sie mehr als ein Feld in Anführungszeichen in der Zeichenfolge haben.
Eine Methode, mit der mehrere in Anführungszeichen gesetzte Felder behandelt werden
Dies ist auch eine Möglichkeit, dies zu lösen. Bei Eingaben, die mehr als ein Komma pro Feld in Anführungszeichen enthalten können, müsste der erste Ausdruck im sed so oft wie der maximale Komma-Inhalt in einem einzelnen Feld wiederholt werden oder bis dahin ändert die Ausgabe überhaupt nicht.
Das Ausführen von sed mit mehr als einem Ausdruck sollte effizienter sein als das Ausführen mehrerer sed-Prozesse und eines "tr", das alle mit offenen Pipes ausgeführt wird.
Dies kann jedoch unerwünschte Folgen haben, wenn die Eingabe nicht richtig formatiert ist. dh geschachtelte Anführungszeichen, nicht abgeschlossene Anführungszeichen.
Mit dem laufenden Beispiel:
Ausgabe:
quelle
sed -r ':r; s/("[^",]+),([^",]*)/\1 \2/g; tr; s/"//g'
.In Perl können Sie dies folgendermaßen
Text::CSV
analysieren:Sie können mit drucken,
Text::CSV
aber in diesem Fall bleiben die Anführungszeichen in der Regel erhalten. (Obwohl, ich würde vorschlagen , - anstatt Strippen Angebote für die Ausgabe, können Sie einfach analysieren mitText::CSV
an erster Stelle).quelle
Ich habe eine Funktion erstellt, die alle Zeichen in der Zeichenfolge durchläuft.
Wenn das Zeichen ein Anführungszeichen ist, wird das Häkchen (b_in_qt) als wahr markiert.
Während b_in_qt wahr ist, werden alle Kommas durch ein Leerzeichen ersetzt.
b_in_qt wird auf false gesetzt, wenn das nächste Komma gefunden wird.
quelle