Diese Website existiert nur weil wir Werbung mit AdSense ausliefern.
Bitte den AdBlocker daher auf dieser Website ausschalten! Danke.

bash: Zeilenumbrüche bedingt ersetzen

Alles rund um die verschiedenen Konsolen und shells sowie die Programmierung unter Linux

Moderator: Moderatoren

Antworten
radiergummi
Member
Member
Beiträge: 54
Registriert: 14. Feb 2009, 12:34

bash: Zeilenumbrüche bedingt ersetzen

Beitrag von radiergummi » 23. Jan 2019, 15:53

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: Alles auswählen

"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: Alles auswählen

"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: Alles auswählen

awk -F';' '$1 ~ /............/ && $0 > 1 { ... }'
oder

Code: Alles auswählen

awk -F';' '/[1-31].[1-12].20[10-50]/ { ... }'
leider klappt schon das nicht.

Die Alternative mit tr

Code: Alles auswählen

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
Zuletzt geändert von radiergummi am 28. Jan 2019, 17:09, insgesamt 2-mal geändert.

Werbung:
Gräfin Klara
Hacker
Hacker
Beiträge: 349
Registriert: 23. Jun 2008, 20:51

Re: bash: Zeilenumbrüche bedingt ersetzen

Beitrag von Gräfin Klara » 23. Jan 2019, 16:26

Code: Alles auswählen

#!/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

radiergummi
Member
Member
Beiträge: 54
Registriert: 14. Feb 2009, 12:34

Re: bash: Zeilenumbrüche bedingt ersetzen

Beitrag von radiergummi » 23. Jan 2019, 16:37

... ich hab's getestet - und es geht!

Jetzt muss ich erst mal grübeln warum ...

Vielen Dank!


radiergummi
Member
Member
Beiträge: 54
Registriert: 14. Feb 2009, 12:34

Re: bash: Zeilenumbrüche bedingt ersetzen

Beitrag von radiergummi » 28. Jan 2019, 18:06

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: Alles auswählen

> "$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: Alles auswählen

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: Alles auswählen

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: Alles auswählen

[ 650 Zeilen gelesen (aus DOS-Format umgewandelt) ]
Wenn ich die Ausgabedatei des bash-scripts Datei_1 mit nano ansehe, erhalte ich

Code: Alles auswählen

[ 135 Zeilen gelesen (aus Mac-Format umgewandelt) ]
Wenn ich die sed-Ausgabe (Datei_2) mit nano öffne, erhalte ich

Code: Alles auswählen

[ 3 Zeilen gelesen ]
Hier habe ich getestet, wieviele Felder die erzeugten Zeilen haben (wie lang sie sind)

Code: Alles auswählen

awk '{print NF}' Rohdaten.csv | sort -n | tail -1
liefert eine maximale Feldanzahl von 14. Das passt.

Die Datei aus dem bash-script

Code: Alles auswählen

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: Alles auswählen

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

Gräfin Klara
Hacker
Hacker
Beiträge: 349
Registriert: 23. Jun 2008, 20:51

Re: bash: Zeilenumbrüche bedingt ersetzen

Beitrag von Gräfin Klara » 28. Jan 2019, 19:12

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

Benutzeravatar
framp
Moderator
Moderator
Beiträge: 4279
Registriert: 6. Jun 2004, 20:57
Wohnort: bei Stuttgart
Kontaktdaten:

Re: bash: Zeilenumbrüche bedingt ersetzen

Beitrag von framp » 28. Jan 2019, 20:11

Dann sollte

Code: Alles auswählen

sed ':a;N;$!ba;s/[^\"]\r\n/\ /g' <file>
funktionieren.

Antworten