Textdatei in mehrere Dateien auftrennen (mit Shellscript oder anders?)

Hallo Liste, ich habe eine Datei (mit Adressen im vCard Format), die ich in viele einzelne Dateien zerlegen möchte. Jeder Block beginnt mit einer Zeile BEGIN:VCARD und endet mit der Zeile END:VCARD Von diesen Blöcken (Adressen) enthält die Datei sehr viele und ich möchte jeden einzelnenn Block inklusive der Anfangs- und End-Zeilen in einer einzelnen Datei haben. Ich bin mir sicher, dass es dazu eine simple Lösung mit einem Shellscript, awk, ... gibt, komme aber selbst nicht darauf, wie es geht. Einen ersten Versuch habe ich gemacht: ------- counter=0 odatei=Einzeladresse${counter}.vcf while read zeile do if test "${zeile}" = "BEGIN:VCARD"; then counter=`expr ${counter} + 1` odatei=Einzeladresse${counter}.vcf fi echo "${zeile}" >> ${odatei} done < Adressen.vcf ------- Das funktioniert fast. Leider hat es einen Haken: In der Datei sind unter anderem Backslashes enthalten. Ein Backslash wird jedoch von meinem Script "aufgefressen", d.h. die Backslasches fehlen nachher. (Aus "\n" wird "n".) Was ggf. mit anderen Zeichen passiert, habe ich mir noch nicht genauer angesehen, befürchte aber Probleme z.B. mit Anführungszeichen. Wer kann mir den entscheidenden Tipp geben, wie ich die Zeilen ohne Veränderungen in die Einzeldateien bekomme? Eine weitere Idee: Vielleicht muss ich die Zeilen gar nicht einlesen, sondern suche mir (mit grep?) die Trennstellen raus und trenne dann (mit head, tail?) die Datei in Stücke. Ich würde mich freuen, wenn mir jemand helfen kann, der das vielleicht einfach so hinschreibt, wie es richtig ist. Ich komme gerade nicht richtig weiter. Gruß Achim -- Um die Liste abzubestellen, schicken Sie eine Mail an: opensuse-de+unsubscribe@opensuse.org Um eine Liste aller verfuegbaren Kommandos zu bekommen, schicken Sie eine Mail an: opensuse-de+help@opensuse.org

Hallo, Am Fre, 02 Feb 2007, Achim Schäfer schrieb: [..]
Einen ersten Versuch habe ich gemacht: counter=0 odatei=Einzeladresse${counter}.vcf while read zeile [..]
Das funktioniert fast. Leider hat es einen Haken: In der Datei sind unter anderem Backslashes enthalten. Ein Backslash wird jedoch von meinem Script "aufgefressen", d.h. die Backslasches fehlen nachher. (Aus "\n" wird "n".)
while read -r zeile
Eine weitere Idee: Vielleicht muss ich die Zeilen gar nicht einlesen, sondern suche mir (mit grep?) die Trennstellen raus und trenne dann (mit head, tail?) die Datei in Stücke.
Mit awk oder perl. ==== UNGETESTET (ich hab hier keine .vcf) ==== #!/usr/bin/gawk -f BEGIN { cnt=0; in_vcard=0; } /BEGIN:VCARD/ { in_vcard=1; cnt++; out="./vcf." cnt; ### Ausgabedateiname, bitte anpassen print > out; next; } in_vcard == 1 { print > out; } /END:VCARD/ { fflush(out); close(out); in_vcard=0; } ==== Wenn du die Ausgabedateinamen noch anpassen willst... -dnh -- we are apt of borg - rpm is futile - you will be dpkg'ed. -- Um die Liste abzubestellen, schicken Sie eine Mail an: opensuse-de+unsubscribe@opensuse.org Um eine Liste aller verfuegbaren Kommandos zu bekommen, schicken Sie eine Mail an: opensuse-de+help@opensuse.org

Hallo, Am Freitag, 2. Februar 2007 01:54 schrieb David Haller:
Einen ersten Versuch habe ich gemacht: counter=0 odatei=Einzeladresse${counter}.vcf while read zeile
[..]
Das funktioniert fast. Leider hat es einen Haken: In der Datei sind unter anderem Backslashes enthalten. Ein Backslash wird jedoch von meinem Script "aufgefressen", d.h. die Backslasches fehlen nachher. (Aus "\n" wird "n".)
while read -r zeile
Danke, das funktioniert so.
Eine weitere Idee: Vielleicht muss ich die Zeilen gar nicht einlesen, sondern suche mir (mit grep?) die Trennstellen raus und trenne dann (mit head, tail?) die Datei in Stücke.
Mit awk oder perl.
==== UNGETESTET (ich hab hier keine .vcf) ==== #!/usr/bin/gawk -f [...]
Das habe ich jetzt auch nicht mehr getestet. Ich werde aber keine der beiden Möglichkeiten nutzen, sondern auf Romans Tipp mit csplit zurückgreifen. Trotzdem vielen Dank. Achim -- Um die Liste abzubestellen, schicken Sie eine Mail an: opensuse-de+unsubscribe@opensuse.org Um eine Liste aller verfuegbaren Kommandos zu bekommen, schicken Sie eine Mail an: opensuse-de+help@opensuse.org

Hallo, On Friday 02 February 2007 00:50:29 Achim Schäfer wrote:
ich habe eine Datei (mit Adressen im vCard Format), die ich in viele einzelne Dateien zerlegen möchte. Jeder Block beginnt mit einer Zeile
BEGIN:VCARD
und endet mit der Zeile
END:VCARD
Waere csplit eine Loesung? Hier kann man wohl recht einfach per Regexp die Zeilen definieren an denen gesplittet wird. csplit -z <file> '/BEGIN\:VCARD/' '{*}' Eventuell noch einen netten Prefix per --prefix= angeben und gut ist. Roman -- Roman Fietze Telemotive AG Büro Mühlhausen

Hallo, Am Freitag, 2. Februar 2007 08:59 schrieb Roman Fietze:
ich habe eine Datei (mit Adressen im vCard Format), die ich in viele einzelne Dateien zerlegen möchte. Jeder Block beginnt mit einer Zeile
BEGIN:VCARD
und endet mit der Zeile
END:VCARD
Waere csplit eine Loesung?
Ja, vielen Dank!
Hier kann man wohl recht einfach per Regexp die Zeilen definieren an denen gesplittet wird.
csplit -z <file> '/BEGIN\:VCARD/' '{*}'
Wunderbar. Die Lösung ist für mich perfekt. Achim -- Um die Liste abzubestellen, schicken Sie eine Mail an: opensuse-de+unsubscribe@opensuse.org Um eine Liste aller verfuegbaren Kommandos zu bekommen, schicken Sie eine Mail an: opensuse-de+help@opensuse.org

Hallo, Am Fre, 02 Feb 2007, Achim Schäfer schrieb:
Am Freitag, 2. Februar 2007 08:59 schrieb Roman Fietze:
ich habe eine Datei (mit Adressen im vCard Format), die ich in viele einzelne Dateien zerlegen möchte. Jeder Block beginnt mit einer Zeile
BEGIN:VCARD
und endet mit der Zeile
END:VCARD [..] csplit -z <file> '/BEGIN\:VCARD/' '{*}'
Wunderbar.
Die Lösung ist für mich perfekt.
Was passiert mit Text zwischen END:VCARD und BEGIN:VCARD? Das wird von meiner awk-Loesung erledigt (ich hab ne Testdatei gebastelt, aber "ungetestet" eben weil's mit realen Daten gerne doch mal was anderes ist ;) -dnh -- "Early to rise, early to bed, makes a man healthy wealthy and dead" -- Terry Pratchett, The Light Fantastic -- Um die Liste abzubestellen, schicken Sie eine Mail an: opensuse-de+unsubscribe@opensuse.org Um eine Liste aller verfuegbaren Kommandos zu bekommen, schicken Sie eine Mail an: opensuse-de+help@opensuse.org

Am Freitag, 2. Februar 2007 23:21 schrieb David Haller:
csplit -z <file> '/BEGIN\:VCARD/' '{*}'
Wunderbar.
Die Lösung ist für mich perfekt.
Was passiert mit Text zwischen END:VCARD und BEGIN:VCARD?
Genau das, was ich gerne hätte: Alles zwischen den Zeilen BEGIN:VCARD und END:VCARD landet jeweils in einer Datei. Genau genommen werden hierbei natürlich nicht beide Zeilen ausgewertet, sondern nur die Anfangszeile.
Das wird von meiner awk-Loesung erledigt
Ist sehr nett von Dir, dass Du das noch bastelst, aber ich brauche das doch jetzt nicht mehr. (Außer, um meine awk Kenntnisse zu vertiefen ;-) ) Gruß, Achim -- Um die Liste abzubestellen, schicken Sie eine Mail an: opensuse-de+unsubscribe@opensuse.org Um eine Liste aller verfuegbaren Kommandos zu bekommen, schicken Sie eine Mail an: opensuse-de+help@opensuse.org

Hallo, Am Sam, 03 Feb 2007, Achim Schäfer schrieb:
Am Freitag, 2. Februar 2007 23:21 schrieb David Haller:
csplit -z <file> '/BEGIN\:VCARD/' '{*}'
Wunderbar.
Die Lösung ist für mich perfekt.
Was passiert mit Text zwischen END:VCARD und BEGIN:VCARD?
Genau das, was ich gerne hätte: Alles zwischen den Zeilen BEGIN:VCARD und END:VCARD landet jeweils in einer Datei.
Andersrum. Das zwischen END und BEGIN! ==== aus der Testdatei ==== und endet mit der Zeile END:VCARD # NOT THIS BEGIN:VCARD foo [..] END:VCARD NOT THIS ==== Was soll mit dem "NOT THIS" passieren? Kann sowas in der Eingabe-Datei vorkommen?
Genau genommen werden hierbei natürlich nicht beide Zeilen ausgewertet, sondern nur die Anfangszeile.
Und genau das würde das "NOT THIS" mit in die Ausgabe schreiben. Die Awk-Lösung könnte man auch noch so umstricken, daß es auch dann funktioniert, wenn BEGIN:VCARD/END:VCARD nicht am Zeilenanfang stehen.
Das wird von meiner awk-Loesung erledigt
Ist sehr nett von Dir, dass Du das noch bastelst, aber ich brauche das doch jetzt nicht mehr.
Das hatte ich doch schon fertig ;) -dnh -- Wie oft kann ein Usernetz benutz werden, bis es abgenutzt ist? [WoKo in dag°] -- Um die Liste abzubestellen, schicken Sie eine Mail an: opensuse-de+unsubscribe@opensuse.org Um eine Liste aller verfuegbaren Kommandos zu bekommen, schicken Sie eine Mail an: opensuse-de+help@opensuse.org

Am Sonntag, 4. Februar 2007 04:06 schrieb David Haller:
csplit -z <file> '/BEGIN\:VCARD/' '{*}' [...] Was passiert mit Text zwischen END:VCARD und BEGIN:VCARD?
Genau das, was ich gerne hätte: Alles zwischen den Zeilen BEGIN:VCARD und END:VCARD landet jeweils in einer Datei.
Andersrum. Das zwischen END und BEGIN!
Oh, da habe ich nicht genau hingesehen, was Du meintest.
==== aus der Testdatei ==== und endet mit der Zeile END:VCARD
# NOT THIS
BEGIN:VCARD foo [..] END:VCARD
NOT THIS ====
Was soll mit dem "NOT THIS" passieren? Kann sowas in der Eingabe-Datei vorkommen?
Kann nicht vorkommen. Und selbst wenn es drin wäre, könnte es in einer beliebigen Ausgabedatei landen. Mich interessiert nur das, was zwischen den BEGIN und END Zeilen steht und alles andere wird sowieso ignoriert. Deshalb ist die csplit Lösung für mich ideal. Ich weiß, dass mit awk mehr möglich ist, brauche es aber hier einfach nicht. Falls ich es woanders brauche, habe ich jetzt Deine Lösung mit awk. Vielen Dank. Gruß Achim -- Um die Liste abzubestellen, schicken Sie eine Mail an: opensuse-de+unsubscribe@opensuse.org Um eine Liste aller verfuegbaren Kommandos zu bekommen, schicken Sie eine Mail an: opensuse-de+help@opensuse.org
participants (3)
-
Achim Schäfer
-
David Haller
-
Roman Fietze