|
Mankind75
Lokalisierungsteam
Anmeldungsdatum: 4. Juni 2007
Beiträge: 3374
|
Guten Abend zusammen, ich habe folgendes Problem bei einer csv-Datei wo ich einige Daten extrahieren möchte. Dabei habe ich an den GNU-Befehl "cut" gedacht und mir einen Einzeiler geschrieben:
cut -d "," -f 27-43 meinedatei.csv Jetzt ist es so, dass in manchen der extrahierten Felder selbst das Trennzeichen "," (in "Strings quoted") steht sowie in manchen Feldern beispielsweise "Nachname, Vorname" (also mit Komma) so dass der Delimiter da wohl auch Alarm schlägt. Meine Frage ist wie ich dies in einem Skript quasi abfangen kann, dass diese Redundanz auch herausfliegt. Wenn ich das Output einmal habe dann kann ich es ja in eine Output-Datei schreiben und die dann nutzen. Bislang habe ich es halt in bash versucht aber auch Perl oder etwas anderes wäre meinerseits okay wenn jemand eine Lösung hat. Es geht halt darum, dass ich Dateien bekomme, die sehr viel Redundanz für die Weiterverarbeitung haben. Vielen Dank schon mal für eure Hilfe.
|
|
seahawk1986
Anmeldungsdatum: 27. Oktober 2006
Beiträge: 11278
|
Ich würde das mit dem csv-Modul von Python machen:
1
2
3
4
5
6
7
8
9
10
11
12
13
14 | #!/usr/bin/env python3
import csv
import sys
for path in sys.argv[1:]:
with open(path, newline='') as csvfile, open(sys.__stdout__.fileno(),
mode=sys.__stdout__.mode,
buffering=1,
encoding=sys.__stdout__.encoding,
errors=sys.__stdout__.errors, newline='') as output:
reader = csv.reader(csvfile, delimiter=',')
writer = csv.writer(output, delimiter=';')
for row in reader:
writer.writerow(row[26:43]) # Indices start a zero, ranges end excluding the last element
|
Das liefert dann für
1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,"Foo, Bar",41,42,43,44,45,46,47
sowas:
$ python3 extract_csv_column_27_to_43.py test.csv
27;28;29;30;31;32;33;34;35;36;37;38;39;Foo, Bar;41;42;43
|
|
Mankind75
Lokalisierungsteam
(Themenstarter)
Anmeldungsdatum: 4. Juni 2007
Beiträge: 3374
|
Das ist ein guter Ansatz danke seahawk1986. Ich kann bei dem Programm welches die CSV-Datei empfängt einstellen welches Trennzeichen ich haben möchte. Das hilft mir sehr weiter.
|
|
shiro
Supporter
Anmeldungsdatum: 20. Juli 2020
Beiträge: 1303
|
Oops... Ich bin wohl etwas spät dran, da das Thema bereits abgeschlossen wurde. Zur Vollständigkeit wollte ich allerdings noch eine allgemeinere Lösung auf Basis von sed beisteuern. Der normale regex ▶ (,|\r?\n|^)([^",\r\n]+|"(?:[^"]|"")*")? ◀ für diese Aufgabe wird wegen des "?:" Konstruktes von sed|(g)awk leider nicht unterstützt. Es muss bei csv Dateien auch davon ausgegangen werden, dass die Felder komplexer gequoted sind und dass ein Feld auch mehrzeiligen Inhalt haben kann. Aus diesem Grund habe ich die für die "Spalten"-Normierung eine Bash-Funktion (csvPRE) geschrieben, die die csv Datei dann leicht durch "cut" oder "(g)awk" behandelbar macht. Damit die extrahierten Spalten wieder in einer Tabellenkalkulation verwendet werden können, habe ich noch eine weitere Bash-Funktion (csvPOST) dazu gepackt. Hier das Beispiel:
# vorn ein ","
# Excel double-Quotes am Anfang (,""") und Ende (""",) in '\"' Äquivalenzen anpassen
# interne '\"' als hex01
# in '"' eingeklammerte felder in hex02 und hex03 einklammern
# loop mit Label L nach in hex02/03 eingebetten "," suchen und "," durch hex04 ersetzten
# wenn ein Feld über mehrere Zeilen verteilt ist, das \n durch hex05 ersetzen
function csvPRE() {
s="${2:-,}"
sed -zr 's/^/'$s'/; s/'$s'"""/'$s'"\x01/g; s/"""'$s'/\x01"'$s'/g; s/([^\\])""/\1\x01/g; s/\\"/\x01/g; s/'$s'"([^"]*)"/'$s'\x02\1\x03/g; s/'$s'"/'$s'\x02/; :L; s/\x02([^\x03]*)'$s'([^\x03]*)/\x02\1\x04\2/g; s/\x02([^\x03]*)\n/\x02\1\x05/g; tL; s/^'$s'//' $1
}
function csvPOST() {
s="${2:-,}"
sed -r 's/\x01/\\"/g; s/(\x02|\x03)/"/g; s/\x04/'$s'/g; s/\x05/\n/g' $1
}
cat - > $$ << **EOF**
Zeile1,aaa,b b,"""c"" cc"
Zeile2,1,,"333, drei,
immer noch drei"
Zeile3,A A,"B,B,B","C,""C"",C"
Zeile4,"Mit \"escaped\" Quotes","und, dann
mehrzeilig,\"hier\"",4711
**EOF**
echo -"Es werden die Spalten 1, 3-4 extrahiert\n"
cat $$
echo -e "\nnun mit Komma\n"
csvPRE $$ | cut -d, -f1,3-4 | csvPOST
echo -e "\nnun mit Semikolon\n"
cat $$ | tr ',' ';' | csvPRE "" ";" | cut -d";" -f1,3-4 | csvPOST "" ";" | sed 's/\\"/""/g'
|
|
Mankind75
Lokalisierungsteam
(Themenstarter)
Anmeldungsdatum: 4. Juni 2007
Beiträge: 3374
|
shiro schrieb: Oops... Ich bin wohl etwas spät dran, da das Thema bereits abgeschlossen wurde.
Ist kein Problem. Ich habe den Thread im Sinne von "WORKSFORME" als gelöst markiert. Danke für deine Idee. Viele Wege führen nach Rom…
|