• Willkommen im Linux Club - dem deutschsprachigen Supportforum für GNU/Linux. Registriere dich kostenlos, um alle Inhalte zu sehen und Fragen zu stellen.

bash: Zeilenumbrüche bedingt ersetzen

Hallo Forum,

ich bekomme von der Bank Kontoumsätze als csv-Datei, die ich in GnuCash importieren möchte.
Das Format von der Bank:
Code:
"Feld1";"Feld2";"Feld3";"Feld4"
"12.03.2018";"BB456";"djfh
sdkjf
lsdfkj
oxcivu
dkfj";"hejtr"
...

Ich würde gerne alle Zeilenumbrüche - vor denen kein Anführungszeichen steht - löschen oder gegen ein Leerzeichen ersetzen, so dass die Datei etwa so aussehen würde:
Code:
"Feld1";"Feld2";"Feld3";"Feld4"
"12.03.2018";"BB456";"djfh sdkjf lsdfkj oxcivu dkfj";"hejtr"
...

Im ersten Schritt wollte ich die Zeilen, die nur die Bruchstücke enthalten, ausfiltern:
Code:
awk -F';' '$1 ~ /............/ && $0 > 1 { ... }'
oder
Code:
awk -F';' '/[1-31].[1-12].20[10-50]/ { ... }'

leider klappt schon das nicht.

Die Alternative mit tr
Code:
tr -d \n < csv-datei.csv
hat auch nicht funktioniert (macht praktisch gar nichts)

Kann mir bitte jemand sagen, wie ich das gewünschte Ergebnis bekommen kann?

Vielen Dank für Tipps.

Gruß,

Radiergummi
 
Code:
#!/bin/bash

FNAME="$1"
[[ -n "$FNAME" && -f "$FNAME" ]] || exit 1
FNTMP="$FNAME.tmp"

> "$FNTMP"
while read -r; do
	if [ "${REPLY: -1}" == \" ]; then
		printf "%s\n" "$REPLY" >> "$FNTMP"
	else
		printf "%s " "$REPLY" >> "$FNTMP"
	fi
done < "$FNAME"

exit 0

Script erwartet sich den Dateinamen
Nicht getestet!

Gruß
Gräfin Klara
 
OP
R

radiergummi

Member
Hallo Forum,
danke für den weiteren Vorschlag, aber ich bin doch noch nicht weiter gekommen. Das [gelöst] habe ich wieder weggenommen.

Wenn ich das bash script
Code:
> "$FNTMP"
while read -r; do
	if [ "${REPLY: -1}" == \" ]; then
		printf "%s\n" "$REPLY" >> "$FNTMP"
	else
		printf "%s " "$REPLY" >> "$FNTMP"
	fi
done < "$FNAME"
auf die Rohdaten loslasse erhalte ich eine Datei_1 mit 0 (Null) Zeilen
Code:
wc -l Datei_1
Eine Zeile als Ergebnis hätte ich noch verstehen können - aber Null?!?
Fehlt da der richtige Abschluss der Datei?

Die Rohdaten selbst bestehen aus 650 Zeilen.

Wenn ich den sed-Befehl
Code:
sed ':a;N;$!ba;s/[^\"]\n/\ /g' <file>
anwende und damit eine Datei_2 erzeuge, hat die laut wc 3 (Drei) Zeilen.

Wenn ich die Rohdaten mit nano öffne, erhalte ich die Meldung
Code:
[ 650 Zeilen gelesen (aus DOS-Format umgewandelt) ]

Wenn ich die Ausgabedatei des bash-scripts Datei_1 mit nano ansehe, erhalte ich
Code:
[ 135 Zeilen gelesen (aus Mac-Format umgewandelt) ]

Wenn ich die sed-Ausgabe (Datei_2) mit nano öffne, erhalte ich
Code:
[ 3 Zeilen gelesen ]

Hier habe ich getestet, wieviele Felder die erzeugten Zeilen haben (wie lang sie sind)
Code:
awk '{print NF}' Rohdaten.csv | sort -n | tail -1
liefert eine maximale Feldanzahl von 14. Das passt.

Die Datei aus dem bash-script
Code:
awk '{print NF}' Datei_1 | sort -n | tail -1
liefert für die längste gelesene Zeile 1609 Felder

Die mit sed erzeugte Datei
Code:
awk '{print NF}' Datei_2 | sort -n | tail -1
liefert für die längste gelesene Zeile 920 Felder

Ich bin mit meinem Latein am Ende und für weitere Tipps dankbar.

Gruß,

Radiergummi
 
Die Datei wurde mit hoher Wahrscheinlichkeit unter Windows erstellt.
Windows verwendet als Zeilenende \r\n und den Zeichensatz UTF-16.
Linux will aber \n und UTF-8, d.h. das csv_file muß vorher entsprechend angepasst werden.

FNAME="/path/datei.csv"
# 1. Umwandeln in UTF-8
iconv -c -t utf-8 "$FNAME" > "$FNAME.utf"
# 2. Das Zeilenende anpassen
dos2unix -b -n "$FNAME.utf" "$FNAME.txt"

Nun das Resultat "/path/datei.csv.txt " durch das script schicken
oder die beiden Zeilen in das script einbauen.

Gruß
Gräfin Klara
 
Oben