Bash csv mit Trennzeichenproblem

seraphym

Cadet 4th Year
Registriert
März 2010
Beiträge
121
Hallo allerseits,

folgendes Problem: Ich habe ein csv mit knapp 45.000 Datensätzen.
Die einzelnen Spalten sind eigentlich mit Kommas getrennt. Allerdings gibt es bei zwei Spalten eine Besonderheit: Die Spalte enthält den Vornamen und Nachnamen von Personen, allerdings im Format "Nachname, Vorname".

Im csv sieht das dann so aus:
spalte1,spalte2,"Nachname, Vorname",spalte4,usw

Ich möchte dieses csv mit ein paar Bash-Scripten auswerten. Allerdings machen mir die "-Trennzeichen massive Probleme.
Ein einfaches
grep liste.csv | cut -d, -f4
zum Beispiel liefert natürlich nur Müll. Auch ein
grep liste.csv | awk {$print $4}
bringt auch nur Quatsch.

Hat jemand eine Idee wie das csv sauber formatiert bekomme? Zum Beispiel alle ,-Delimiter durch Semikolons ersetzen (aber was ist mit "Nachname, Vorname")? Schwierig.
Vielleicht stehe ich auch einfach nur auf dem Schlauch.

Grüße,
Sera
 
Wäre vielleicht auch der Import in Excel, ändern und Export nach csv eine Option? In Excel hast du ja deutlich einfachere Möglichkeiten deine Änderungen nur auf diese bestimmte Spalte zu beschränken.
 
  • Gefällt mir
Reaktionen: Raijin und PHuV
Da hat aber jemand schon bei der Erstellung der CSV-Datei gepennt. Hier würde ich mich mal an den Generierer dieser Datei wenden, und es gleich richtig machen lassen, Spalten mit ; Trennen, und Feldtrenner mit " und ,.
Ergänzung ()

cvzone schrieb:
Wäre vielleicht auch der Import in Excel, ändern und Export nach csv eine Option? In Excel hast du ja deutlich einfachere Möglichkeiten deine Änderungen nur auf diese bestimmte Spalte zu beschränken.
Nicht nur vielleicht, man kann in Excel ganz klar alle Trenner konfigurieren und vorgeben. ;)

@seraphym

Du wirst, falls Du die Quelle der Erzeugung nicht ändern kannst, um eine mehrstufige Vorverarbeitung weiterkommen. Daher, wie Hibbelharry es riet, mit RegEx entweder "," zu etwas neuem ändern, oder alle Spaltentrenner zu ; und die Feldtrenner zu "," belassen. Für RegEx ist Perl ganz prima.

Da RegEx durchaus eine Herausforderung ist, würde ich es mit solchen Testern austesten:
https://regex101.com/
https://regexr.com/
 
Zuletzt bearbeitet:
  • Gefällt mir
Reaktionen: DJMadMax und Raijin
Lösung: mit sed s'/\"//'g die " entfernen:

sed s'/\"//'g liste.csv
Ergebnis:
zeile1, spalte1,spalte2,Nachname, Vorname,spalte4,usw
zeile2, spalte1,spalte2,Nachname, Vorname,spalte4,usw
zeile3, spalte1,spalte2,Nachname, Vorname,spalte4,usw



Sollen zusätzlich die Kommata durch Semikolons ersetzt werden:
sed s'/\"//'g liste.csv | sed s'/,/;/'g
Ergebnis:
zeile1; spalte1;spalte2;Nachname; Vorname;spalte4;usw
zeile2; spalte1;spalte2;Nachname; Vorname;spalte4;usw
zeile3; spalte1;spalte2;Nachname; Vorname;spalte4;usw

Sollen die Felder separiert werden;
sed s'/\"//'g liste.csv | awk -F',' '{print $4 , "|", $6, "|", $3, "|", $2 ";", $5, ";", $1}'
Ergebnis:
Nachname | spalte4 | spalte2 | spalte1; Vorname ; zeile1
Nachname | spalte4 | spalte2 | spalte1; Vorname ; zeile2
Nachname | spalte4 | spalte2 | spalte1; Vorname ; zeile3
 
Zuletzt bearbeitet:
muss es den bash sein?
Bei Powershell gibts das cmdlt "import-csv" und "export-csv" das wäre ein Einzeiler und du wärst am Ziel, und die pwsh gibts ja auch für Linux.

PowerShell:
import-csv <File> | export-csv <File> -delimiter ';' -NoTypeInformation
 
Zuletzt bearbeitet:
  • Gefällt mir
Reaktionen: KitKat::new()
Schafft der auch die mit "," Feldtrenner?

Unter Linux kann man das auch recht einfach mit IFS und Co. machen, oder man setzt gleich csvtool ein. Das kann anscheinend mit den "," Feldern auch recht gut umgehen.
 
@PHuV
Sehr gut erklärt! Generell kann man dem nichts mehr hinzufügen.

@cvzone hat aber auch nicht Unrecht.
Die Datei lässt sich so zwar nicht mehr sauber in Excel oder Access einlesen, allerdings wird sich der Importfehler ausschließlich auf die Datensätze beschränken, die eben das Komma im Datensatz und nicht nur als Trennzeichen haben.

Von daher wäre es vermutlich das Leichteste, die Daten so (also mit Excel oder Access) einzulesen und dann die betreffenden Datensätze, die falsch eingelesen wurden, manuell zu überarbeiten.

Und ja:
Beim Exportieren als CSV (generell Textdatei) IMMER einen sogenannten "Textqualifizierer" verwenden. Dann lassen sich nicht nur Felder, sondern auch Datentypen (also Text oder Zahl) beim nächsten Import wieder sauber herstellen.
 
  • Gefällt mir
Reaktionen: PHuV
Nutz nen ordentlichen Parser. Regex ist das komplett falsche Tool und sed und Co. sind erst recht Quatsch.

Morgen sieht die CSV so aus
Code:
spalte1,spalte2,"Nachname, Vorname",spalte4
"teil 1 teil 2","teil 3.1, teil 3.2; teil 3.3","Nachname, Vorname",spalte4
und du fängst wieder von vorn an.
PHuV schrieb:
Da hat aber jemand schon bei der Erstellung der CSV-Datei gepennt. Hier würde ich mich mal an den Generierer dieser Datei wenden, und es gleich richtig machen lassen, Spalten mit ; Trennen, und Feldtrenner mit " und ,.
An der CSV ist überhaupt nichts falsch. Was ich als Trenner nehme ist mir überlassen und wenn es das Leerzeichen ist. Wenn ich die Felder ordentlich Quote, hat damit kein Tool Probleme. Eben nur solche Frickellösungen wie "splitte am Komma, alles ist ne Spalte". Und ja, es gibt auch CSVs die Newlines als solche umsetzen. Und wenn bei deiner Lösung nun ein Semikolin als Trenner und auch in den Feldern vorkommt, bricht das Kartenhaus wieder zusammen...

Im Sinne von
Code:
1,2 "2      

        2.1" 3 4
5 6 7 8
9 10 11 12
PowerShell hat ein Cmdlet inklusive
PowerShell:
$ "1,2,3,4`n5,6,7,8`n9,10,11,12" | ConvertFrom-Csv -Header c1,c2,c3,c4

c1 c2 c3 c4
-- -- -- --
1  2  3  4
5  6  7  8
9  10 11 12

$ "`"1,2`",2,3,4`n5,6,7,8`n9,10,11,12" | ConvertFrom-Csv -Header c1,c2,c3,c4

c1  c2 c3 c4
--  -- -- --
1,2 2  3  4
5   6  7  8
9   10 11 12

$ "1,2 `"2               2.1`" 3 4`n5 6 7 8`n9 10 11 12" | ConvertFrom-Csv -Delimiter ' ' -Header c1,c2,c3,c4

c1  c2                  c3 c4
--  --                  -- --
1,2 2               2.1 3  4
5   6                   7  8
9   10                  11 12

"1,2 `"2       `n`n        2.1`" 3 4`n5 6 7 8`n9 10 11 12" | ConvertFrom-Csv -Delimiter ' ' -Header c1,c2,c3,c4

c1  c2                    c3 c4
--  --                    -- --
1,2 2       …             3  4
5   6                     7  8
9   10                    11 12
Absolut kein Problem mit nem ordentlichen Parser.

csvtool macht das auch korrekt
Code:
$ csvtool -t " " col 1 csv.csv
"1,2"

5

9
$ csvtool -t " " col 2 csv.csv
"2


        2.1"

6

10
 
Zuletzt bearbeitet:
  • Gefällt mir
Reaktionen: NotNerdNotDau und sikarr
@feynman : Das ist tatsächlich der Weg, den ich auch gegangen wäre. Effektiv zwei Arbeitsschritte. Allerdings klingen die Ausführungen von @Yuuri durchaus plausibel, auch wenn ich mir gerade nicht die Mühe machen möchte, das nachzubauen ;)
 
Yuuri schrieb:
Was ich als Trenner nehme ist mir überlassen und wenn es das Leerzeichen ist.
Natürlich ist das CSV hier nicht gut designt. Ich habe jahrelang mit diversen Datenformaten gearbeitet (XML, EDI wie EDIFACT, Sedas, IDOC, Ansi X12, VDA, Odette,....), glaub mir, ich kenne mich damit sehr gut aus. Du wirst bei Uneindeutigkeit IMMER das Problem der Verarbeitung bzw. Parsierbarkeit haben.
Yuuri schrieb:
Was ich als Trenner nehme ist mir überlassen und wenn es das Leerzeichen ist.
Wenn Du allein für Dich rumwurstelst, ja, sobald Du aber mit anderen Systemen und Geschäftspartner kommunizierst, nein. Dafür gibt es internationale Standards. CSV ist kein definiertes und normiertes Standardformat.
Yuuri schrieb:
Wenn ich die Felder ordentlich Quote, hat damit kein Tool Probleme.
Einspruch, Du hast permanent Probleme damit. Durfte ich erst wieder mit einer YAML-Datei erleben, wo ein Kennwort $ enthielt, und Gitlab in der Konfiguration das trotz Escape nicht gefressen hatte. Genau das gleiche Drama mit Tomcat Konfiguration, Java und Proxykonfiguration wie Passwörtern und Co. mit " \/& usw. auf Linux wie Windows Ebene, wenn das allerlei von Konsolen und Startscripten weggefrühstückt wird.
Yuuri schrieb:
Eben nur solche Frickellösungen wie "splitte am Komma, alles ist ne Spalte". Und ja, es gibt auch CSVs die Newlines als solche umsetzen. Und wenn bei deiner Lösung nun ein Semikolin als Trenner und auch in den Feldern vorkommt, bricht das Kartenhaus wieder zusammen...
Dann darf eben das ; nicht im Feld auftauchen, ganz einfach, oder es muß als Ausnahme entsprechend korrekt markiert werden (Escape).

Alles eine Frage per Design. Nur leider pennen die Leute bei der Erstellung und Strukturierung, und man muß den Leuten erst mal erklären, was korrekte Datenformate sind. Feld- und Spaltentrenner zu mischen ist eben kein valides Datenformat, genauso einfach wild Zeilentrenner reinhauen (kennen wir zur Genüge von SAP-Kollegen, die in Feldern alles mögliche reinknallen). Und noch lustiger wird es, wenn dann Asiaten hier plötzlich mit UFT16 Zeichen kommen, obwohl das Dateiformat in ISO-88591 geliefert und gekennzeichnet wird, und keine BOM vorhanden ist.

Daher, gutes Datenformat: alles ist eindeutig, und bei der Datenerstellung wird darauf korrekt geachtet.
Schlechtes Datenformat, nichts ist eindeutig, und die Datenerzeuger sorgen auch nicht für korrekte Dateien anhand des Datenformates, (z.B. ist im XML Header ISO-Format angegeben, obwohl UFT8-Zeichen vorkommen, keine korrektes Escaping usw.).

Wenn man das verstanden hat, kann man es auch entsprechend von den Datenerzeugern einfordern, oder man macht, wie eben vorgeschlagen, eine mehrstufige Bearbeitung, um aus einem schlechten Dateiformat ein gutes zu bauen.
 
Zuletzt bearbeitet:
PHuV schrieb:
Natürlich ist das CSV hier nicht gut designt. Ich habe jahrelang mit diversen Datenformaten gearbeitet (XML, EDI wie EDIFACT, Sedas, IDOC, Ansi X12, ....), glaub mir, ich kenne mich damit sehr gut aus. Du wirst bei Uneindeutigkeit IMMER das Problem der Verarbeitung bzw. Parsierbarkeit haben.
Welche Uneindeutigkeit? Das Feld in der CSV vom TE ist eindeutig ein Feld, da es durch den Feldbegrenzer " eingegrenzt wird. Innerhalb eines Feldbegrenzers kann ganz regulär ein Feldtrenner [,;\t] eingesetzt werden. Mit bash und cut kommst du da nicht zum Ziel, mit Regex genauso nicht. Also schnapp dir einfach nen ordentlichen Parser und gut ist.

In RFC4180 werden auch die Regeln des Formats vorgegeben.
  1. jede Zeile ein Datensatz
    Code:
    aaa,bbb,ccc CRLF
    zzz,yyy,xxx CRLF
  2. EOF CRLF ist optional
    Code:
    aaa,bbb,ccc CRLF
    zzz,yyy,xxx
  3. Header sind optional
    Code:
    field_name,field_name,field_name CRLF
    aaa,bbb,ccc CRLF
    zzz,yyy,xxx CRLF
  4. jedes Feld durch Komma , getrennt
    Code:
    aaa,bbb,ccc
  5. Felder optional durch Quotes eingegrenzt
    Code:
    "aaa","bbb","ccc" CRLF
    zzz,yyy,xxx
  6. Felder mit CRLF, Quotes und Kommas sollten in Quotes gesetzt werden
    Code:
    "aaa","b CRLF
    bb","ccc" CRLF
    zzz,yyy,xxx
  7. wenn Quotes im Feld vorkommen, müssen diese doppelt escaped werden
    Code:
    "aaa","b""bb","ccc"
Regel 6 bedeutet also, dass der Datensatz
Code:
spalte1,spalte2,"Nachname, Vorname",spalte4,usw
komplett gültig ist. Der TE hat ergo ne valide CSV vor sich liegen.

Funfact: Übrigens gibts in der ASCII-Tabelle bereits Steuerzeichen für Group 0x1d und Record 0x1e Separator (zusätzlich zum Unit Separator 0x1f), die man auch verwenden könnte. Das gilt aber eben nur für den Export, über welchen der TE keine Kontrolle hat und zudem auch nicht standardkonform sind.
PHuV schrieb:
Einspruch, Du hast permanent Probleme damit. Durfte ich erst wieder mit einer YAML-Datei erleben, wo ein Kennwort $ enthielt, und Gitlab in der Konfiguration das trotz Escape nicht gefressen hatte. Genau das gleiche Drama mit Tomcat Konfiguration, Java und Proxykonfiguration wie Passwörtern und Co. mit " \/& usw. auf Linux wie Windows Ebene, wenn das allerlei von Konsolen und Startscripten weggefrühstückt wird.
Wie du an meinen Aufrufen oben siehst, haben PowerShells ConvertTo-Csv und ConvertFrom-Csv, sowie csvtool keine Probleme damit.

YAML ist ne ganz andere Story oder wie war das mit Norwegens ISO2 Code, welcher als Boolean geparst wird? Nicht umsonst gibts YAML Strict. Raw Strings in YAML werden mit Hochkommas eingegrenzt. Ein ordentlicher Parser sollte das unterscheiden können, wenn er auch NO als false parsen kann. Es gibt halt einen Unterschied zwischen 'foo$bar' und "foo$bar". Hochkommas sollten so geparst werden, wie sie da zu sehen sind, Anführungszeichen erhalten zusätzliches Parsing.

http://yaml-online-parser.appspot.com/
Zeigt mir auch an was ich erwarte:
Code:
- 'foo $ bar'
- 'foo \$ bar'
- 'foo \\$ bar'
- "foo \\$ bar"
- "foo \\\\$ bar"
- "foo \\\\\\$ bar"

[
  "foo $ bar",
  "foo \\$ bar",
  "foo \\\\$ bar",
  "foo \\$ bar",
  "foo \\\\$ bar",
  "foo \\\\\\$ bar"
]
YAML ist nun aber auch kein sinnvolles Format zur Serialisierung oder zum Transport. TOML ist imho ne noch perfidere Krankheit. Vor zwei Tagen von KDL gelesen...

Das hat aber primär nichts mit dem Format, sondern rein dem Parser zu tun. Es gibt auch genug .env-Parser, die bei
Code:
FOO="BAR"
die Quotes erhalten. Manche entfernen sie. Manche ersetzen noch Variablen...
PHuV schrieb:
Dann darf eben das ; nicht im Feld auftauchen, ganz einfach, oder es muß als Ausnahme entsprechend korrekt markiert werden (Escape).
"ganz einfach" ist eben Hanebüchen. Dann übermittel ich eben Artikelbeschreibungen ohne Newlines als Wall of Text im Fließtext. Artikeleigenschaften? Klar, entfernen wir den Trenner, kann der Fernseher halt statt OLED, 55", HDMI eben OLED 55 HDMI. OLED in Version 55 oder 55 HDMI Slots? Achso, 55 Zoll, OLED und HDMI...

Gut, wenn der Empfänger das nicht verarbeiten "kann" - mir egal, sein Pech. Wenn ich die Daten aber so erhalte, kann ich da natürlich rumpfuschen, "bis mein System damit umgehen kann" oder man nutzt einfach nen regulären Parser, der das schlucken kann und korrekt verarbeitet. Cloud, Kubernetes, Docker, 128-Core-CPUs, aber heute stolpert man immer noch über CSVs, weil man diese mit bash und cut verarbeiten will, da man zu faul ist sich nen simplen Parser zu suchen. ¯\(ツ)/¯ Wegen nem Feldbegrenzer " mal eben alle Quotes aus dem Text schmeißen...

Dein Einwand hat aber ein weiteres Problem. Weshalb escapen? Ein Parser, der keine Escape-Sequenzen kennt, knallt dir einfach ne weitere Spalte rein und endet die vorherige Spalte mit \ (so wie im Falle von cut). Dann hast du wahlweise bei zehn Feldern, wovon fünf gequotet sind und je ein Komma enthalten 15 Felder und die Daten passen vorn und hinten nicht mehr. Ggf. knallt es dann in der Warenwirtschaft, Backend, Frontend, ... (je nachdem wie du es weiterverarbeitest) und du hast keine Ahnung wieso und bist am Debuggen von 5 Mio Datensätzen und das alles nur, weil du statt nem ordentlichen Parser cut verwendet hast. Mit viel Glück, Geschick und weiterer Pfuscherei könnte man damit auch gleich untersuchen, ob dadurch irgendwas exploitbar ist, weil deine "12. Spalte" (die nicht existiert), in irgend einem Szenario einen Payload darstellen kann. Und schon bist du durch deinen dilletantischen Import einer CSV gehackt worden.

Das erinnert mich grad an The Perl Jam: Exploiting a 20 Year-old Vulnerability

Ne Spalte mehr oder weniger macht ja nichts...

SQL-Injections funktionieren auf die selbe Art und Weise und die existieren massenhaft, genauso wie auch XSS. Und wie verlinkt bricht sich selbst Perl dabei ein Bein ab - nicht auf identische Weise, aber durch das selbe Prinzip.
PHuV schrieb:
Daher, gutes Datenformat: alles ist eindeutig, und bei der Datenerstellung wird darauf korrekt geachtet.
Sein obiges Beispiel ist eindeutig. Es gibt in CSV ja noch genauso nicht nur die Backslash-Escape-Variante (eigentlich überhaupt nicht), sondern auch einfach doppelte Feldtrenner (die eigentlich korrekte Weise nach RFC).

PowerShell und csvtool funktionieren bspw. nur mit doppelten Feldtrennern.

3.csv
Code:
1 "2   \"  2.1" 3 4
5 6 7 8
9 10 11 12
4.csv
Code:
1 "2   ""  2.1" 3 4
5 6 7 8
9 10 11 12
Code:
$ csvtool -t ' ' col 2 3.csv
2   \
6
10
$ csvtool -t ' ' col 2 4.csv
"2   ""  2.1"
6
10
Code:
$ .\csv.ps1                                                                                        
a b          c  d
- -          -  -
1 2   \         2.1"
5 6          7  8
9 10         11 12
1 2   "  2.1 3  4
5 6          7  8
9 10         11 12

Aber abseits von CSV ist bei XML bspw. überhaupt nicht "klar" (also eigentlich schon, aber kaum ein Parser/Serializer unterstützt es korrekt), wann <![CDATA[ ... ]]> gesetzt wird. Einige lassen es weg, andere lassen es weg und escapen, manche Serializer geben mir keine Möglichkeit CDATA nicht zu setzen, sondern serialisieren am liebsten jedes Feld damit, manche Parser schlucken es, manche ignorieren es komplett, manche übernehmen es mit in den Wert...

Also nur weil ein Format "eindeutig" ist, heißt es nicht, dass jede Implementierung auch korrekt arbeitet, da je nachdem der übliche Pfusch am Bau vorhanden ist. Ich hab auch schon genug Fälle gesehen, wo man manuell JSON serialisiert hat (nicht mit json_encode(), json.dump(), JsonConvert.SerializeObject(), JSON.stringify()...) und dann selbst an Strings gefummelt wurde... Oder SQL durch String-Operationen zusammensetzen, statt nen Query Builder zu benutzen.

Wenn man es nicht besser weiß - gut, kann man nachhelfen. Wer es weiß aber nicht will - typischer Kurpfuscher.
PHuV schrieb:
Wenn man das verstanden hat, kann man es auch entsprechend von den Datenerzeugern einfordern, oder man macht, wie eben vorgeschlagen, eine mehrstufige Bearbeitung, um aus einem schlechten Dateiformat ein gutes zu bauen.
Oder man nutzt eben einen ordentlichen Parser und kein Gefrickel mit bash, cut, Regex, string replace, ... und verfälscht die Daten im Vorlauf nicht. :O

Aber der TE hat halt das Problem der bash. Die ist für solche Fälle nunmal gänzlich ungeeignet, außer er will jedes Feld jedes Datensatzes einzeln auslesen und auswerten (mittels bspw. csvtool). Also einfach ne geeignetere Shell (PowerShell) nehmen oder mindestens ne Scriptsprache (PHP, Python, Node, ...) anwerfen womit er die Datei ordentlich parsen kann, damit es nicht zu Fehlern kommt.
 
  • Gefällt mir
Reaktionen: NotNerdNotDau, jb_alvarado, DubZ und 2 andere
Mal eine ganz banale Frage an @seraphym

Handelt es sich hierbei um einen einmaligen Vorgang oder wirst du häufiger vor der Aufgabe stehen, solch eine Datei zu parsen?

Ist ersteres der Fall, kamnst du dich eigentlich jeder der hier gezeigten Lösungen bedienen, im letzteren Fall sollte der Ablauf natürlich möglichst effizient geskriptet werden. Lösungen wie Excel und dergleichen fielen damit so oder so aus.
 
Ui ui ui ui, kriege ich dieses Wespennest wieder zu? ;)
Ich hätte nicht gedacht soviel Staub aufzuwirbeln.
Der Tip mit csvtool war sehr hilfreich, danke an @PHuV !
@Raijin : Meine Kollegen müssen mehrere csv's einmal pro Woche auswerten. Die csv's kommen automatisiert, ich baue jetzt zwei, drei Bashscripte zum parsen und poste das Ergebnis ins Sharepoint. Idealerweise muss man dann nicht mehr händisch eingreifen.
 
  • Gefällt mir
Reaktionen: PHuV und Raijin
seraphym schrieb:
@Raijin : Meine Kollegen müssen mehrere csv's einmal pro Woche auswerten. Die csv's kommen automatisiert, ich baue jetzt zwei, drei Bashscripte zum parsen und poste das Ergebnis ins Sharepoint. Idealerweise muss man dann nicht mehr händisch eingreifen.
Dann solltest Du mal schauen, ob Du einen Einfluß auf die Erzeugung des Quellformates nehmen kannst. Ich empfehle Vorgaben für das Format, und ; oder anderen Zeichen wie | als Spaltentrenner, was eher nicht in einem Textfeld vorkommen kann oder sollte.

@Yuuri

Bitte nicht falsch verstehen, wenn ich jetzt nicht ausführlich auf Deinen Text eingehe, ich weiß ihn auf alle Fälle wertzuschätzen, weil Du klar hier auch Deine Erfahrungen und Kompetenzen hast. In einigen Dingen stimme ich Dir zu, wie mit dem gescheiten Parser, der das besser macht, und Datenformate als Standards nichts nützen, wenn sie eh anders interpretiert werden.

Anders als Du sehe ich hier keine Probleme, die Bash zu verwenden, die heute sogar inline eine prima und komplette Verarbeitung von Strings und Arrays bietet. Aber ich stimme Dir zu, das sollte nur eine erste oder einfache Möglichkeit sein, wenn es bessere Alternativen gibt, sollte man sie nutzen, z.B. von den jeweiligen Datenbanken die Tools. Es kommt eben darauf an, was man genau machen will. ;)
Und anders als Du meine ich eben, daß der Spaltentrenner anders als ein Feldtrenner sein sollte, und wenn, dann nur per Escape als gleiches Zeichen gelten sollte. Das erleichtert die Verarbeitung ungemein. Natürlich kann ein spezialisierter Parser damit umgeben. Aber sobald z.B. sowas vorkommt:
Feld,Feld,"Text\0d\0a ,Text\0d\0a",Feld
hast Du hier ein Problem. Mit einer eindeutigen Definition (nur mal so als Beispiel)
  • Spaltentrenner = ;
  • Feldtrenner = ,
  • EOL = |
Feld;Feld;"Text\0d\0a ,Text\0d\0a";Feld|
kann man das noch ohne weiteres parsieren.

Daher, je nach Perspektive kann man das so oder so sehen. Meine Parole ist hier, KISS, und eindeutiges Datenformat mit klaren Definition von Trennern.

@All

Blöde Frage, wie bekomme ich es eigentlich in Excel hin, die Trennzeichen beim Exportieren zu bestimmen? Beim Import einer CSV-Datei kann ich ja einiges beim Einlesen vorgeben, aber seltsamerweise kann ich das beim Speichern der CSV-Datei selbst nicht.
Ich kann direkt in Windows den Spaltentrenner vorgeben.
https://qastack.com.de/superuser/60...the-comma-as-a-default-delimiter-in-csv-files

Wie sage ich aber, daß ich ein Feld mit " " haben will? Ich habe es schon per Formatierung als Textfeld probiert, er erzeugt mir dann nur diese Ausgabe

1631801604421.png


aaa ; bbb ; ccc ; ddd ; eee fff ; ggg, hhh

Wie und wo kommen da jetzt die " automatisch rein? Wenn ich es selbst direkt in die Zelle eintrage, kommt dann klarerweise sowas raus:

aaa ; bbb ; ccc ; ddd ; eee fff ;"""ggg, hhh"""

Übrigens sieht man hier, daß per Standard Excel ; als Feldtrenner hat. Daher frage ich mich, was dann die CSV-Datei erzeugt hat? Excel war das schon mal nicht.
 
Zuletzt bearbeitet:
Yuuri schrieb:
An der CSV ist überhaupt nichts falsch. Was ich als Trenner nehme ist mir überlassen und wenn es das Leerzeichen ist.
Ich hoffe, dass du mit dieser Einstellung nicht beruflich mit Adressqualifizierung oder sonstiger Aufbereitung von Kundendaten zu tun hast.

Natürlich kann man manuelle Imports schreiben und jedwede Ausnahmen definieren. Bei unbestimmten Kundendaten ist das aber absolutes Harakiri!

Ich MUSS sehen können, was der Kunde anliefert, allein schon, um den Kunden entsprechend darauf hinweisen zu können. Wie so oft hat der Kunde vermutlich keine Ahnung und auch keine Möglichkeit, die Daten anders zu senden. Mit dieser Info ist man dann fein raus, bereitet die Daten so weit wie möglich maschinell, gegebenenfalls zum Teil manuell (immer in Absprache mit dem Kunden) auf und weist stets auf die entsprechenden Fehler und mögliche Probleme bei der Weiterverarbeitung hin.

Was DU hingegen machst, ist das Kundenproblem zu deinem Eigenen werden zu lassen und wenn dann etwas schiefgeht, bist du voll haftbar.

Ich will mal sehen, wie du dich mit deinem tollen selbstgeschriebenen Parser im Streitfall rausredest, weil es irgendwo einen ungewollten Zeilensprung gab und hunderttausende Kunden plötzlich falsche Daten zugeordnet bekommen haben - am Besten noch per Briefpost mit Fremddaten anderer Kunden, damit der wirtschaftliche Schaden so richtig Kreise zieht.

Sorry, aber "sauber" ist anders. Ich habe 13 Jahre lang in genau dem Bereich gearbeitet und zich tausende Textdateien (csv ubd alles andere) verarbeitet. Hätte ich solch eine Einstellung an den Tag gelegt, wäre ich vermutlich am 1. Tag fristlos gekündigt worden, das ist nämlich grob fahrlässig.
 
  • Gefällt mir
Reaktionen: PHuV
Die CSV ist meiner Ansicht nach völlig valide. Bei CSV-Dateien gibt es:
  • Enclosure (z.B. Doppelte Anführungszeichen) - Innerhalb dieser wird das Trennzeichen ignoriert
  • Escape-Character (z.B. Backslash) - Damit kann ein Enclosure-Zeichen Escaped werden, um es als Zeichen und nicht als Enclosure zu lesen
  • Delimiter (z.B. Komma) - Trennzeichen, sofern nicht innerhalb einer "Enclosure"
Es gibt sogar ein RFC dazu (https://tools.ietf.org/html/rfc4180).

Sprich: Ich würde da auch eher Python, PHP, JavaScript oder ne andere Script-Sprache mit nem ECHTEN CSV-Parser nehmen.
 
  • Gefällt mir
Reaktionen: jb_alvarado
DJMadMax schrieb:
Sorry, aber "sauber" ist anders. Ich habe 13 Jahre lang in genau dem Bereich gearbeitet und zich tausende Textdateien (csv ubd alles andere) verarbeitet. Hätte ich solch eine Einstellung an den Tag gelegt, wäre ich vermutlich am 1. Tag fristlos gekündigt worden, das ist nämlich grob fahrlässig.
Was willst du mit deinem inhaltsleeren Post eigentlich aussagen?

Bei deinem ganzen Geschreibsel bezweifel ich wirklich, dass du die Aussage(n) meines/r Posts überhaupt ansatzweise verstanden hast...

Auf welcher Basis argumentierst du eigentlich? Willst du mir erzählen, dass ein CSV-Parser bei CSV-Dateien unangebracht wäre? Oder hängst du dich wirklich nur an der theoretischen Aussage eines Leerzeichens als evtl. Trenner auf?

Falls du es nicht kapierst, nochmal explizit für dich:

In CSV kann man mit üblichen Tools die Trenner variabel setzen. Diese Aussage impliziert nicht, dass es geschehen muss oder soll. Wenn ich hier also höre, dass der Trenner durch ein Semikolon ersetzt werden soll, weil jener Trenner auch im Feld vorkommt, rollen sich mir die Fußnägel hoch, weil das
  1. vollkommen valides CSV ist
  2. eine zwangsweise Manipulation der Daten mit allen möglichen Nebeneffekten bedeutet
Deshalb kam ich mit dem Beispiel des Leerzeichens als Trenner um die Absurdität dessen aufzuzeigen. Statt also irgendwas zu ersetzen oder zu escapen oder sonstige Scherzveranstaltungen durchzuführen, habe ich lediglich dafür gestimmt einen ordentlichen CSV-Parser einzusetzen. Nicht mehr, nicht weniger. Auch ein Semikolon ist nicht standardkonform (auch wenn es viele machen), sowie werden Feldbegrenzer nicht durch einen Backslash escaped. Mag sein, dass es Implementierungen gibt, der offizielle Standard besagt aber eine andere Verfahrensweise durch die Dopplung des Begrenzers. Ein konformer CSV-Parser kommt aber auch mit Leerzeichen klar und die Erkennung kann auch automatisch erfolgen.

Hast du einen Punkt gegen den Einsatz eines CSV-Parsers? Hast du einen Punkt für den Einsatz der Shell mit cut, awk und Co? Regex? Nein? Warum schreibst du dann solch inhaltsloses Blabla?

Aber dass du dich genau an diesem Fitzelchen aufgeilst, zeigt wunderbar auf dass du sinnloses Cherry Picking betreibst und diesen einen Satz komplett aus dem Kontext reißt, gepaart mit irrelevantem Zeug und "fristlos kündigen" und Blablabla. Weil was interessiert mich was in den Daten steht, wenn ich es halt ordentlich parsen kann? Und dass der TE sowieso keine Kontrolle über den Export hat, hab ich auch erwähnt.

Wichtig ist, das Format zu parsen und nicht die Daten zu interpretieren oder manipulieren.

Gratulation, Leseverständnis 100 Punkte. Next please...
DJMadMax schrieb:
Ich hoffe, dass du mit dieser Einstellung nicht beruflich mit Adressqualifizierung oder sonstiger Aufbereitung von Kundendaten zu tun hast.
Hm danke, ich hab dann doch etwas mehr als nur mit schnöden CSVs zu tun. So ungefähr XML, YAML, JSON, TOML, JSON und REST APIs, GraphQL, SOAP, SQL, Binärdaten und wie der ganze Klamauk sich noch nennt und der wievielte Standard vom Standard es auch ist. Die "Aufbereitung" von Kundendaten bekomm ich ganz gut hin - u.a. über mehrere Schnittstellen zur Überführung von Daten von/zu unterschiedlichen Warenwirtschaften. Was rechtfertige ich mich eigentlich, das solltest du mit "13 Jahren Erfahrung" selbst wissen...
DJMadMax schrieb:
Natürlich kann man manuelle Imports schreiben und jedwede Ausnahmen definieren. Bei unbestimmten Kundendaten ist das aber absolutes Harakiri!
Wo hab ich sowas erzählt? Ich hab auf nen CSV-Parser verwiesen. Wo ist da die Rede von "manuellen Imports"? Und die "unbestimmten Kundendaten" sind vollkommen irrelevant, denn ich muss das Format parsen und nicht die Kundendaten interpretieren! "Manuelle Imports" sind für mich eben Frickellösungen wie oben Genanntes, aber kein Parser... Ist "manuelles Exportieren" der Einsatz eines XML Serializers in deinen Augen? Interpretieren kann ich im Nachhinein, aber das ist ne Frage, die der TE nicht mal ansatzweise gestellt hat. Er will nur das Formt parsen.
DJMadMax schrieb:
Was DU hingegen machst, ist das Kundenproblem zu deinem Eigenen werden zu lassen und wenn dann etwas schiefgeht, bist du voll haftbar.
Ich mache gar nichts. Ich nehm mir nen Parser, stell auf seine Konvention um und fertig ist der Lack. Da geht gar nichts schief, außer der Kunde sendet invalide Daten. Was er nicht macht, denn der TE hat uns das Paradebeispiel eines validen CSV-Auszugs gegeben!
DJMadMax schrieb:
Ich will mal sehen, wie du dich mit deinem tollen selbstgeschriebenen Parser im Streitfall rausredest, weil es irgendwo einen ungewollten Zeilensprung gab und hunderttausende Kunden plötzlich falsche Daten zugeordnet bekommen haben - am Besten noch per Briefpost mit Fremddaten anderer Kunden, damit der wirtschaftliche Schaden so richtig Kreise zieht.
Wieso soll ich mich rausreden? Und welchen "selbst geschriebenen" Parser nutze ich, wenn ich die Cmdlets ConvertTo-Csv sowie ConvertFrom-Csv (alternativ Import-Csv und Export-Csv) verwende oder auf csvtools für die Konsole verweise? Was habe ich dort selbst geschrieben? Und wenn ich die CSV in ne SQL-DB importiere und dann darauf operiere... Da ist auch nichts "selbst geschrieben".

Ist das für dich ein selbst geschriebener Serializer/Parser?
PowerShell:
PS > $json = [pscustomobject]@{foo="bar"; bar="baz"},[pscustomobject]@{foo="foobar"; bar="barbaz"} | ConvertTo-Json; $json; $json | ConvertFrom-Json
[
  {
    "foo": "bar",
    "bar": "baz"
  },
  {
    "foo": "foobar",
    "bar": "barbaz"
  }
]

foo    bar
---    ---
bar    baz
foobar barbaz
DJMadMax schrieb:
Sorry, aber "sauber" ist anders.
Genau, einen CSV-Parser zu verwenden ist "unsauber". Klaro. Und XML "parse" ich mit Regex und XPath wende ich auf GraphQL an. ¯\(ツ)

Lies doch das nächste Mal bitte den ganzen Post...
DJMadMax schrieb:
Ich habe 13 Jahre lang in genau dem Bereich gearbeitet und zich tausende Textdateien (csv ubd alles andere) verarbeitet.
Schön für die Schwanzvergleiche, nur sagt das null komma nichts über die Qualifikation und Erfahrung aus. Und danke, ich arbeite auch seit vielen Jahren als Softwarentwickler. Brot und Butter sind bei mir Datenverarbeitung... Da brauchst du mir nicht mit Formaten wie CSV, XML, JSON und Co. ankommen. Zumal ich den "Luxus" von Datenstrukturen und Objekten habe und ich nicht auf serialisierten Daten arbeiten muss.
DJMadMax schrieb:
Hätte ich solch eine Einstellung an den Tag gelegt, wäre ich vermutlich am 1. Tag fristlos gekündigt worden, das ist nämlich grob fahrlässig.
Bei der Auffassungsgabe allerdings berechtigt...
PHuV schrieb:
Wie und wo kommen da jetzt die " automatisch rein?
Wenn der Text den Trenner oder ein Newline enthält. Ganz nach RFC also.

1631831638359.png


1631831752768.png


CSV UTF-8 mit BOM Marker. Und es wird auch wieder ordentlich importiert (wenn man es ordentlich über den Wizard macht). Die Erkennung hat auch problemlos funktioniert, einzig mit der Raute als Trenner gibts wohl irgendein Problem.

1631831999644.png

PHuV schrieb:
Übrigens sieht man hier, daß per Standard Excel ; als Feldtrenner hat.
Du hast doch bereits festgestellt, dass es locale dependent ist...?

1631830932768.png


Pack ich da | rein, wird eben der Trenner genutzt. Excel hat ergo überhaupt keinen Standard, sondern richtet sich ausschließlich nach den Systemeinstellungen. Einzig Komma exportiert Excel trotzdem als Semikolon.



Aber egal... Das Thema ist durch, der TE hat nun genug Hinweise bekommen. Er nutzt nun erstmal csvtool.
 
  • Gefällt mir
Reaktionen: NotNerdNotDau und DubZ
Zurück
Oben