Splitten einer Datei (aus einer großen Datei viele kleine machen)

D

drm

Eroberer
Ich habe folgendes Problem:

Es gibt folgende Datei "personen" mit diesem Aufbau:

Person Anfang
Name: Becker
Vorname: Max
Kd.-Nr.: 0038475
;

Person Anfang
Name: Schmidt
Vorname: Felix
Kd.-Nr.: 0038476
;

Person Anfang
Name: Segger
Vorname: Uwe
Kd.-Nr.: 0038479
;

usw.

Diese Datei personen enthält ca. 2000 Kunden, jetzt sollen aber nicht mehr alle Kunden in der selben Datei stehen sondern jeder Kunde soll in eine eigene Datei geschrieben werden.

Meine Idee:
- ich suche mir alle Einträge heraus die mit Person anfangen und bis zu dem ; gehen und schreibe diese in neue Dateien,
- die Datei möchte ich kunde_[Nachname des entsprechenden Kunden] nennen.

Hat jemand einen Vorschlag wie ich das umsetzen könnte, da meine Unixkenntnisse noch nicht so ausgeprägt sind?!
.
.
.
EDIT (autom. Beitragszusammenführung) :
.

Hat denn keiner einen Lösungsansatz für mich?
Würde mich echt freuen...
 
Zuletzt bearbeitet:
Moin
so wie ich die Sache sehe, solltest du mal in die man von sed
sehen. Es ist ein Ansatz, nicht mehr. :D

Gruss Diirch
 
Und mit grep's lässt sich das nicht so einfach realisieren?
Dann schau ich mal nach sed...
 
Ich würde die Datei Zeilenweise auslesen und nach nem Semikolon Parsen, dabei alle Zeilen in eine Datei schreiben, bis eben das Semikolon auftaucht und dann in eine neue Datei schreiben. Vielleicht so (ungetestet):

Code:
#!/bin/sh

path='/path/to/file'
no=1

while read line
do
   for file in `ls`
   do
      if [ $line != ';' ]
      then
         echo $line >> $path/$no.txt
      else
         $no=`expr $no + 1`
      fi
   done
done

Gruß
D.
 
@madfool: Danke für den Ansatz. Allerdings finde ich die for-Schleife überflüssig, die while-Schleife müsste reichen, damit durchlaufe ich jede Zeile von "personen" , schaue ob kein ";" vorhanden ist und schreibe es so lange in eine Datei und fange von vorne an. Krieg ich aber so irgendwie nicht so richtig ans rennen und ist nicht wirklich performant.

Kann man es nicht mit nawk machen:
Code:
nawk '$1 ~ "Person" && $2 "Anfang" { print $1, $2 }' personen
So bekomme ich schon mal 2000 Ergebnisse geliefert die mir aber nur die erste n beiden Zeile ausgeben. Wie kann ich es anstellen dass er bis zum ";" alles ausgibt?
 
Ok, mein Script oben war natürlich Bullshit... es war zu früh am Morgen ;)
Die for-Schleife waren Überreste einer Copy&Paste Aktion außerdem fehlte die Eingabe für die while-Schleife:

Code:
#!/bin/sh

path='./'
no=1

while read line
do
   if [ $line != ";" ]
   then
      echo $line >> $path/$no.txt
   else
      no=`expr $no + 1`
   fi
done<test.txt

Das hab ich mit einer Datei die so:

Code:
aaaaa
aaa
aaaaaaaa
;
bbbbbbbb
bbbbbb
bbbbbbbbbbbb
;
cccccccc
ccccccccccccccccc
ccccccccccccc
;

aussieht getestet. Und es hat funktioniert.

Gruß
D.
 
Das sieht schon einmal super aus :-)
Allerdings soll die Zeile mit dem ";" noch mit in die Datei geschrieben werden, da ich gerade gesehen habe das teilweise die Kundeninformationen auch so enden können: Kd.-Nr.: 0038475;
Also brauche ich die Zeile mit in den einzelnen Dateien, und selbst wenn nur ein ";" als letztes angegeben wird brauche ich das auch in der Datei. Ansonsten funktioniert es schon perfekt *freu* Vielen Dank madfool!!!
 
Zuletzt bearbeitet:
Aber das bekommst du bestimmt jetzt noch selber hin oder?

Gruß
D.
 
Mmh, bin gerade am überlegen:
- wenn ich die Zeile if [ $line != ";" ] durch if [ $line != "Person Anfang ersetze" ] passt es schon einmal nicht.
Wahrscheinlich ist es total easy...

- Aah, ich werde es so probieren:
Code:
#!/bin/sh

path='./'
no=1

while read line
do
   if [ $line != ";" ]
   then
      echo $line >> $path/$no.txt
   else
      echo $line >> $path/$no.txt
      no=`expr $no + 1`
   fi
done<test.txt

Hab's gerade getestet, läuft jetzt wunderbar und auch das ";" wird mit in die Datei geschrieben. Oh man, da hatte ich ein Brett vorm Kopf *g*

###################################

Zwei Fragen habe ich noch dazu:
- Wie würde ich es anstellen wenn ich ausschließlich von "Person" bis ";" alles in eine Datei schreiben möchte, so das z. B. Kommentare nicht mit übernommen werden?
- Wenn ich Leerzeichen dazwischen habe kommt die Meldung "kein Argument" und es wird für die leere Zeile eine neue Datei erzeugt. Wie kann ich das beheben?
 
Zuletzt bearbeitet:
Hallo
Das ist nicht so trivial wie es ausschaut.
Soll ja auch noch performant laufen und der Name verwendet werden.
Ich habe hier einen kleinen schnellen "ugly" Perlhack anzubieten.
Ungetestet und verbesserungswürdig.
ACHTUNG KEINE FEHLERPRÜFUNG!
Code:
perl -anle 'if(/^[^;\n]/i){$h.="$_\n"}else {if($h=~/Name: ([^\s ]*)?\n.*/sg){open OUT,">$1";print OUT "$h";$h=""}}' datei

Schau mal ob es funktioniert.
Allerdings, wenn leine Name: HIER vorkommt, wird nix ausgegeben. Das bedeutet, der Bereich verschwindet.

Gruß Wolfgang
EDIT
OK War zu spät, bin unterbrochen worden (Telefon)
Also vergiss es!
Noch ein Tipp:
Vermeide expr, das macht die Sache langsam, weil es ein externer Prozess ist.
Verwende statt dessen das Builid
$((x++))
Kannst du ja mal mit time testen! Du wirst dich wundern!


NAchtrag zum expr im Vergleich zu ((x++)), für alle die es nicht glauben:

wolle@Nietzsche:/tmp
$ x=0;time for i in $(seq 1 10000); do x=$(expr $x + 1) ;done; echo $x

real 0m23.799s
user 0m4.504s
sys 0m19.217s
10000
wolle@Nietzsche:/tmp
$ x=0;time for i in $(seq 1 10000); do ((x++)) ;done; echo $x

real 0m0.123s
user 0m0.108s
sys 0m0.012s
10000
Auf einer dual core 3ghz getestet!
Und 10000 ist wirklich nicht groß.
 
Zuletzt bearbeitet:
Dann werde ich ab jetzt standardmäßig das Builid $((x++)) verwenden, bei einer Datei mit 2000 einträgen ist das ja kein Problem, aber wenn man mit großen Datenmengen arbeitet... du hast mich überzeugt.

Von Perl habe ich übrigens 0,0 Ahnung, deswegen werde ich versuchen das Problem mit Unix zu lösen, wenn ich erfolgreich bin werde ich das mal berichten.
 
Zurück
Oben