ubuntuusers.de

"Wilde" Textdatei in CSV umwandeln

Status: Ungelöst | Ubuntu-Version: Ubuntu 7.04 (Feisty Fawn)
Antworten |

Weller

Anmeldungsdatum:
10. Januar 2007

Beiträge: 104

Wohnort: Gebhardshain

Hallo!
Ich habe eine Textdatei bekommen mit wild zusammengewürfelten Adressen. Leider kein CR nach jeder Adresse und kein vernünftiges Trennzeichen zwischen den einzelnen Daten.
Gibt es eine Möglichkeit das in ordentliches CSV umzuwandeln zur Weiterverarbeitung?

Hier ein Datenbeispiel:
KdNr., Zusatz, Vorname Name Straße; PLZ Ort KdNr., Zusatz, Vorname Name Straße; PLZ Ort KdNr., Zusatz, Vorname Name Straße; PLZ Ort KdNr., Zusatz, Vorname Name Straße; PLZ Ort KdNr., Zusatz, Vorname Name Straße; PLZ Ort KdNr., Zusatz, Vorname Name Straße; PLZ Ort KdNr., Zusatz, Vorname Name Straße; PLZ Ort KdNr., Zusatz, Vorname Name Straße; PLZ Ort

So steht der Kram einfach hintereinander ☹
Problem: man kann nichtmal das ASCII Zeichen 32 als Trenner zwischen Ort und KdNr. nehmen, weil es ja auch Orte bestehende aus mehreren Worten gibt...

Hat jmd. eine Idee?

Gruß,
Andreas Welelr

xoanon

Anmeldungsdatum:
12. Dezember 2006

Beiträge: 121

Wohnort: Hamburg

naja \^^ plz ist ne zahl ... kdnr auch ?

RegExp und Perl sind dein freund!

s/(\d\d\d\d\d)\s(.*?)\s(\d+)/$1\s$2\n$3/g # ok nun sind zeilen umbrüche drinne:

KdNr., Zusatz, Vorname Name Straße; PLZ Ort
KdNr., Zusatz, Vorname Name Straße; PLZ Ort
KdNr., Zusatz, Vorname Name Straße; PLZ Ort
KdNr., Zusatz, Vorname Name Straße; PLZ Ort

Öde wird "Vorname Name Straße". Zum einen könntest du dir eine Datei erstellen mit allen zeilen bei denen "Vorname Name Straße" nicht auf /(.*?)\s(.*?)\s(.*?)\s(\d+[a-z]?)/ passt: "Maria Bärbel Mustermann Vogelstrasse 12a". Und die halt per Hand nacharbeiten. Gemein sind die Strassen. "Stiller Winkel", "Zum Brunnen" etc ... ohne Strassen Verzeichnisse wüste ich nicht wie man das sicher aufdröseln kann.

z.B. "Bärbel Mustermann Waldweg 1" → String, space, String, space, string, space , zahl + u.u. ein buchstabe → /(.*?)\s(.*?)\s(.*?)\s(\d+[a-z]?)/

u.li

Avatar von u.li

Anmeldungsdatum:
12. Mai 2007

Beiträge: 503

Wohnort: Hürth

Das sollte funktionieren, solange alle Personen nur jeweils einen Vor- und Nachnamen haben:

#!/usr/bin/env perl -w

use strict;
use warnings;

while ( <> ) {
	# in einzelne Einträge teilen
	while ( s/(\d+),(.+?)(\d+,|$)/$3/ ) 	{
		my $kdnr = $1;
		#den Eintrag zerschnippeln
		print "$kdnr:$1:$2:$3:$4:$5:$6\n" if( $2 =~ /\s?(.*?),\s(.+?)\s(.+?)\s(.+?);\s?(\d+)\s(.+)/ );
	}
} 


(speichern und aufrufen mit ./skript.pl datei)

Wenn mehrere Vornamen abgespeichert sind, gibt es wie xoanon schon gesagt hat, keine Möglichkeit (die ich sehe), das automatisch auseinanderzufummeln.

xoanon

Anmeldungsdatum:
12. Dezember 2006

Beiträge: 121

Wohnort: Hamburg

bei den Nachnamen muss man auf jeden fall mit \s rechnen: "el Moncef", "van Braun", "von Gummersbach" "de Sade" usw ...

Weller

(Themenstarter)

Anmeldungsdatum:
10. Januar 2007

Beiträge: 104

Wohnort: Gebhardshain

Hallo!
Irgendwie wird ein Großteil übergangen. Aus meinen ursprünglich etwa 4 MB Daten wurden nach durchlauf des geposteten Scripts etwa 20 kB...

Gruß,
Andreas

user_unknown

Avatar von user_unknown

Anmeldungsdatum:
10. August 2005

Beiträge: 17622

Wohnort: Berlin

Wenn Du ein wenig anonymisierte Sampledaten schickst wird es wahrscheinlich noch besser.

Mit

head urdata | sed 's/[b-zB-Z]/a/g' > anon.sample


sollte das leicht möglich sein.
Die 10 Zeilen manuell umbrechen, damit man die Gemeinsamkeiten besser sieht.

Weller

(Themenstarter)

Anmeldungsdatum:
10. Januar 2007

Beiträge: 104

Wohnort: Gebhardshain

aA0A, A, aaaa. aa. aaaa aaaaaaa aaaaaaa. 27; 49536 aaaaaa aA0Aa, A, aaaaaa aaaaaaa aaaaaaaaaaaa 2 a; 37085 aöaaaaaaa aA0Aaa, A, aa. aaaaaaa aaaaaaaaaa aaaaaaaaaa. 12; 66117 aaaaaaüaaaa aaaaaaaaaaaaaa; 66117 aaaaaaüaaaa aA0aAa, A, aaaaaaaaa aaaaa aA0aa, A, aaaaa aaaaaa aaaaaaaaa aaaaaaa 422; 44805 aaaaaa aA0aaa, A, Aaaaaaaaa aaaaa aaaaaaaa. 34; 96215 aaaaaaaaaaa aA0aA, A, aaaaa aaaaaa aaaaaaa 196; 48599 aaaaaa aaaaaaaaa. 28; 48599 aaaaaa aA0aa, A, aaa aaaaaaa aaaaaaaaaaaa 35; 03055 aaaaaaa aA0aaa, A, aaaaaaa aaaaa aaaaaaaa. 44; 45881 aaaaaaaaaaaaa aaaaaaaaaaaaa. 11; 48159 aüaaaaa aA0aa, A, aaaaaaa aaaaa aaaaaaaaaaaaa 9; 95652 aaaaaaaaaa aA0aaa, A, aaaaaaaa aaaaaa aA0aa, A, aüaaaaa aaaaa aaaaaaaaaa. 54; 01129 aaaaaaa aA0aaa, A, aa. aaaaaa aaaaa aaaaaaaaaa aaa. 14; 99086 aaaaaa aA0aaa, A, aaaaa aaaaaa aaaaaa aaa 1; 74653 aüaaaaaaa aA0a, A, aaaaaa aaaaaaaa aA0aa, A, aaaaa aaa aaaaaaaaa-aaaaa-aaa. 18; 36043 aaaaa aA0aaa, A, aaaaaaaa aaaaaaaaa aaaaaaaaaaaaaaa. 87; 98708 aaaaaa aA0aaa, A, aaaaaa aaaaaaa aaaaaaaa. 6; 90542 aaaaaaaa aA0aa, A, aaaaa aaaaaa aaaaaaaaaa aaa. 38; 15234 aaaaaaaaa / aaaa aaaaaaaaaaa. 7; 15236 aaaaaaaaa / aaaa aA0aa, A, aaaa.aa.aaa. aaa aaaa aaaaaaaaaaaa 7 a; 85567 aaaaaaa aA0aaa, A, aaaaaaaa aaaaaa aaaaa-aaaaa-aaa. 35; 50827 aöaa aA0aaa, A, aaaaaa aaaaaa-aaaaaaa aaüaa aaaaa 19; 15754 aaaaaaaa / aa aaaaaa aA0aaa, A, aaaaa aaaaaaaaaaa aaa aaaa 688; 27498 aaaaaaaaa aA0aa, A, aa. aaaaaa aaaaa aaaaaaaaaa aaa. 14; 99086 aaaaaa aA0aaa, A, aaaa. aa. aaaa aaaaaaa aA0a, A, aa. aaaaa aaaaaaaaaa aaa aaa aaaaaaaa 11; 49808 aaaaaa aA0aaa, A, aaaa aüaaa aaaaaaaaa 13; 66802 Üaaaaaaaa aaa. a. aaaaaaaaa- aaaaaa 1; 66287 aaaaaaaaaaa aA0aaA, A, aaaaaaa aaaaaa aaaaaa. 59; 51069 aöaa aA0a, A, aaa aaaaaaaaa Aa aaa aaaaaaüaaa 20A; 27721 aaaaaaaaaa aaaaaaaaaa aaaa aaa; 00001 aaaaaaüaaaaa aA0aaa, A, aaaa aaaa aaaaaaaaaaaaa 4; 27478 aaaaaaaa Aa Aaaaa aaaaa 2; 27472 aaaaaaaa aA0aaa, A, aaaaa Aaaa aöaaaaaaa. 27; 99734 aaaaaaaaaa

(Editiert von user unknown - das sollte reichen).

user_unknown

Avatar von user_unknown

Anmeldungsdatum:
10. August 2005

Beiträge: 17622

Wohnort: Berlin

Sorry - das war meine Unachtsamkeit - die Zeilen sind ja noch nicht umgebrochen - also wirft 'head' viel mehr Daten raus.

Die Kundennummer ist also ein keine Nummer, zumindest keine dezimale, sondern mehr ein Identifier oder wie man das nennen will.

Mit Umbrüchen sieht es wohl so aus - sicher kein Problem für die Perl-Fraktion:

aA0A, A, aaaa. aa. aaaa aaaaaaa aaaaaaa. 27; 49536 aaaaaa
aA0Aa, A, aaaaaa aaaaaaa aaaaaaaaaaaa 2 a; 37085 aöaaaaaaa
aA0Aaa, A, aa. aaaaaaa aaaaaaaaaa aaaaaaaaaa. 12; 66117 aaaaaaüaaaa aaaaaaaaaaaaaa; 66117 aaaaaaüaaaa
aA0aAa, A, aaaaaaaaa aaaaa aA0aa, A, aaaaa aaaaaa aaaaaaaaa aaaaaaa 422; 44805 aaaaaa
aA0aaa, A, Aaaaaaaaa aaaaa aaaaaaaa. 34; 96215 aaaaaaaaaaa
aA0aA, A, aaaaa aaaaaa aaaaaaa 196; 48599 aaaaaa aaaaaaaaa. 28; 48599 aaaaaa
aA0aa, A, aaa aaaaaaa aaaaaaaaaaaa 35; 03055 aaaaaaa
aA0aaa, A, aaaaaaa aaaaa aaaaaaaa. 44; 45881 aaaaaaaaaaaaa aaaaaaaaaaaaa. 11; 48159 aüaaaaa
aA0aa, A, aaaaaaa aaaaa aaaaaaaaaaaaa 9; 95652 aaaaaaaaaa aA0aaa, A, aaaaaaaa aaaaaa
aA0aa, A, aüaaaaa aaaaa aaaaaaaaaa. 54; 01129 aaaaaaa
aA0aaa, A, aa. aaaaaa aaaaa aaaaaaaaaa aaa. 14; 99086 aaaaaa
aA0aaa, A, aaaaa aaaaaa aaaaaa aaa 1; 74653 aüaaaaaaa
aA0a, A, aaaaaa aaaaaaaa aA0aa, A, aaaaa aaa aaaaaaaaa-aaaaa-aaa. 18; 36043 aaaaa
aA0aaa, A, aaaaaaaa aaaaaaaaa aaaaaaaaaaaaaaa. 87; 98708 aaaaaa
aA0aaa, A, aaaaaa aaaaaaa aaaaaaaa. 6; 90542 aaaaaaaa
aA0aa, A, aaaaa aaaaaa aaaaaaaaaa aaa. 38; 15234 aaaaaaaaa / aaaa aaaaaaaaaaa. 7; 15236 aaaaaaaaa / aaaa
aA0aa, A, aaaa.aa.aaa. aaa aaaa aaaaaaaaaaaa 7 a; 85567 aaaaaaa
aA0aaa, A, aaaaaaaa aaaaaa aaaaa-aaaaa-aaa. 35; 50827 aöaa
aA0aaa, A, aaaaaa aaaaaa-aaaaaaa aaüaa aaaaa 19; 15754 aaaaaaaa / aa aaaaaa
aA0aaa, A, aaaaa aaaaaaaaaaa aaa aaaa 688; 27498 aaaaaaaaa
aA0aa, A, aa. aaaaaa aaaaa aaaaaaaaaa aaa. 14; 99086 aaaaaa
aA0aaa, A, aaaa. aa. aaaa aaaaaaa aA0a, A, aa. aaaaa aaaaaaaaaa aaa aaa aaaaaaaa 11; 49808 aaaaaa
aA0aaa, A, aaaa aüaaa aaaaaaaaa 13; 66802 Üaaaaaaaa aaa. a. aaaaaaaaa- aaaaaa 1; 66287 aaaaaaaaaaa
aA0aaA, A, aaaaaaa aaaaaa aaaaaa. 59; 51069 aöaa
aA0a, A, aaa aaaaaaaaa Aa aaa aaaaaaüaaa 20A; 27721 aaaaaaaaaa aaaaaaaaaa aaaa aaa; 00001 aaaaaaüaaaaa
...

So wie es aussieht gibt es teilweise mehrere PLZ und auch sonstige Kuriositäten - aber der Kunden-ID sieht identifizierbar aus: [a-zA-Z]A0[a-zA-Z]*,

Weller

(Themenstarter)

Anmeldungsdatum:
10. Januar 2007

Beiträge: 104

Wohnort: Gebhardshain

So wie es aussieht gibt es teilweise mehrere PLZ und auch sonstige Kuriositäten - aber der Kunden-ID sieht identifizierbar aus: [a-zA-Z]A0[a-zA-Z]*,

Hallo!
Hab' mich noch etwas damit beschäftigt:
Also ([D][A-R][0-9][A-Z]+),\s([A-E]),\s([^;]+);\s(\d{5})\s(\w+) scheint einen Datensatz recht gut zu beschreiben...
Aber wie jetzt in CSV zwängen???

Gruß,
Andreas Weller

xoanon

Anmeldungsdatum:
12. Dezember 2006

Beiträge: 121

Wohnort: Hamburg

mit

s/([D][A-R][0-9][A-Z]+),\s([A-E]),\s([^;]+);\s(\d{5})\s(\w+)/$1,$2,"$3",$4,"$5"\n/

... das reicht normalerweise.

Ansonsten gibs für Perl noch sehr schöne CPAN Module die sich auch ums " und ; escapen kümmern (es gibt da gewisse "standards" die ich aber nicht so 100%ig kenne).

DBI Treiber: DBD::CSV mag ich recht gerne. Mann arbeitet mit SQL Befehlen auf CSV Tabellen - Sehr schön wenn's grösser wird als man dachte und irgendwann sich sagt "so, jetzt aber richtig". Hat einen gewissen "overhead" da mann halt mit sql befehlen Zeilen einfügt. Hat sich bei mir aber schon rel. oft gelohnt.

Ansonsten Text::CSV_XS... Wenn du überhaupt perl kannst/magst.

Sid_Burn

Anmeldungsdatum:
23. Oktober 2004

Beiträge: 2159

Ansonsten gibs für Perl noch sehr schöne CPAN Module die sich auch ums " und ; escapen kümmern (es gibt da gewisse "standards" die ich aber nicht so 100%ig kenne).

Wenn ein Semikolion im Datensatz vorkommt, dann wird der Datensatz mit Anführungszeichen begrenzt.
Beispiel:

"<datensatz>";<datensatz>;<datensatz>;"<datensatz>"

Sollte ein Anführungszeichen danach im Datensatz auftreten, dann wird das Anführungszeichen durch zwei Anführungszeichen escaped.
beispiel:

"Er sagte; ""Hallo""";foo;bar;"hallo; Welt"

Das Beispiel hat 4 Datensätze.
1) Er sagte; "Hallo"
2) foo
3) bar
4) hallo; welt

Man sieht immer wieder Falsche Lösungen wo einfach Sinnlos an ";" getrennt wird, oder wo man beim Schreiben nicht beachtet ob ein Semikolion im Datensatz vorkommt. Vorallem bei den Bash Leuten sehr beliebt.

Anhand dieses Beispiel sieht man eigentlich schon das der Aufwand komplex genug ist was die Verwendung von Modulen rechtfertig. Und zweitens. Das deine Substitution ebenso Falsch ist, und diese Sonderfälle nicht beachtet.

P.S.:
Es gibt natürlich unterschiedliche Trennzeichen und Möglichkeiten CSV Dateien zu Beschreiben, auch kann das Escapen durch en Backslash vorkommen. Oder es werden wirklich mal Kommata verwendet anstatt Semikolions. 😉 Aber Semikolion und das Anführungszeichen durch zwei aufeinanderfolgende zu Escapen ist so schon weit verbreitet. Es ist z.B. auch das Format das OpenOffice.org Calc Standardmäßig so akzeptiert.

Antworten |