Zeilen zusammenfügen wenn Zeilenanzahl unbekannt (sed)

Vom einfachen Programm zum fertigen Debian-Paket, Fragen rund um Programmiersprachen, Scripting und Lizenzierung.
Antworten
nihilist
Beiträge: 430
Registriert: 27.04.2006 21:17:06
Kontaktdaten:

Zeilen zusammenfügen wenn Zeilenanzahl unbekannt (sed)

Beitrag von nihilist » 02.05.2011 00:38:37

Hi,
Ich würde gerne die Datei
/var/lib/apt/lists/ftp.de.debian.org_debian_dists_wheezy_main_binary-i386_Packages

Code: Alles auswählen

[...]
Package: 2ping
Priority: optional
Section: net
Installed-Size: 172
Maintainer: Ryan Finnie <ryan@finnie.org>
Architecture: all
Version: 1.0-1
Depends: perl
Recommends: perl-modules, libio-socket-inet6-perl
Suggests: libdigest-sha-perl, libdigest-crc-perl
Filename: pool/main/2/2ping/2ping_1.0-1_all.deb
Size: 28426
MD5sum: 1c2c2fa7dc43ba8ade57bccb5c7c9bcf
SHA1: 130f50c4c34ca0dca527df8f14418c815455bfee
SHA256: 801877b60b38f6782ba0c2647a3538d12de742bbe3e75322a159d4cfcf3110a3
Description: Ping utility to determine directional packet loss
 2ping is a bi-directional ping utility. It uses 3-way pings (akin to
 TCP SYN, SYN/ACK, ACK) and after-the-fact state comparison between a
 2ping listener and a 2ping client to determine which direction packet
 loss occurs.
Homepage: http://www.finnie.org/software/2ping/
[...]
in ein csv "verwandeln" um sie dann in mysql o.ä. importieren zu können.

So weit bin ich gekommen:
Mit

Code: Alles auswählen

sed -e 's/^.*: //' -e :a -e '$!N;s/\n / /;ta' -e 'P;D' $f > tmp
sed -e 's/$/;/' -e ' s/^;$//'  tmp > output.csv
lösche ich die Namen vor dem Doppelpunkt, Mache aus "Description" eine Zeile und setze ein ";" hinter das feld.
->

Code: Alles auswählen

 2ping;
optional;
net;
172;
Ryan Finnie <ryan@finnie.org>;
all;
1.0-1;
perl;
perl-modules, libio-socket-inet6-perl;
libdigest-sha-perl, libdigest-crc-perl;
pool/main/2/2ping/2ping_1.0-1_all.deb;
28426;
1c2c2fa7dc43ba8ade57bccb5c7c9bcf;
130f50c4c34ca0dca527df8f14418c815455bfee;
801877b60b38f6782ba0c2647a3538d12de742bbe3e75322a159d4cfcf3110a3;
Ping utility to determine directional packet loss 2ping is a bi-directional ping utility. It uses 3-way pings (akin to TCP SYN, SYN/ACK, ACK) and after-the-fact state comparison between a 2ping listener and a 2ping client to determine which direction packet loss occurs.;
http://www.finnie.org/software/2ping/;
Um einen Datensatz pro Zeile zu bekommen würde ich eigentlich mit

Code: Alles auswählen

sed -n ;N;N;N;s/;\n//g' file > output.csv
untereinander liegende Zeilen zusammenfügen.
Problem ist, ich weiß nicht wie viele Zeilen ein Datensatz enthält da nicht alle Pakete alle Felder besitzen.
Zeilen zusammenlegen bis eine leere Zeile kommt wäre die Lösung, nur fehlt mir der Ansatz mit sed oder ähnlichem. :)

Benutzeravatar
Meillo
Moderator
Beiträge: 9247
Registriert: 21.06.2005 14:55:06
Wohnort: Balmora
Kontaktdaten:

Re: Zeilen zusammenfügen wenn Zeilenanzahl unbekannt (sed)

Beitrag von Meillo » 02.05.2011 11:14:08

nihilist hat geschrieben:Hi,
Ich würde gerne die Datei
/var/lib/apt/lists/ftp.de.debian.org_debian_dists_wheezy_main_binary-i386_Packages
[...]
in ein csv "verwandeln" um sie dann in mysql o.ä. importieren zu können.
Problem ist, ich weiß nicht wie viele Zeilen ein Datensatz enthält da nicht alle Pakete alle Felder besitzen.
Dann wirst du mit diesem Ansatz ein grosses Problem haben. Denn eine CSV-Datei ist wie eine Tabelle organisiert, mit festen Spalten. Jeder Datensatz muss also die gleichen Spalten in der gleichen Reihenfolge haben. Du brauchst also eine Liste aller Spalten die due haben willst, dann musst du die Textdaten einlesen, die Spalten sortieren, evtl. fehlende Spalten mit einer Art NULL-Werten fuellen, evtl. zusaetzliche Felder ignorieren und dann ausgeben. Dein bisheriger Ansatz funktioniert nur wenn die Eingabedaten zufaellig gleichfoermig sind.

Ich wuerde dafuer zu Perl greifen. Das hat fertige CSV-Module die auch Randfaelle (wie Strichpunkte in den Feldern) korrekt behandeln.


Noch was zum sed-Code:

Code: Alles auswählen

sed -e 's/^.*: //' -e :a -e '$!N;s/\n / /;ta' -e 'P;D' $f > tmp
sed -e 's/$/;/' -e ' s/^;$//'  tmp > output.csv
Mehrere -e Parameter kann man meist zu seinem zusammenfassen indem du die Teile mit Strichpunkten trennst. Bei labels aber kann das schief gehen, da diese bei manchen Implementierungen bis an's Zeilenende gehen.

RegExps in sed sind immer gierig, /^.*: / sollte demnach korrekterweise /^[^:]*: / lauten. Besser noch /^[^:]*: /.

Die RegExp /\n / wird von vielen sed-Implementierungen nicht erkannt werden, da der Zeilenumbruch nicht zur Zeile gehoert und damit nicht gematched werden kann. Verwende /^[ \t]/ stattdessen.
Mache aus "Description" eine Zeile und setze ein ";" hinter das feld.
Evtl. ist das Format fuer die Paketbeschreibungen komplett RFC822 folgend. Damit kann jede Zeile umgebrochen sein, wie das bei Description der Fall ist.

Um einen Datensatz pro Zeile zu bekommen würde ich eigentlich mit

Code: Alles auswählen

sed -n ;N;N;N;s/;\n//g' file > output.csv
untereinander liegende Zeilen zusammenfügen.
Problem ist, ich weiß nicht wie viele Zeilen ein Datensatz enthält da nicht alle Pakete alle Felder besitzen.
Zeilen zusammenlegen bis eine leere Zeile kommt wäre die Lösung, nur fehlt mir der Ansatz mit sed oder ähnlichem. :)
``Oder aehnlichem'' war schon der richtige Stichpunkt. Du kannst ja beliebige Filter kombinieren. Z.B. awk. ;-)

Code: Alles auswählen

awk '/^$/{print;next} {printf($0)}'

... aber wie oben gesagt, dein bisheriger Ansatz kann dein Problem nicht korrekt loesen. Da muss man schon groessere Kaliber auffahren.
Use ed once in a while!

nihilist
Beiträge: 430
Registriert: 27.04.2006 21:17:06
Kontaktdaten:

Re: Zeilen zusammenfügen wenn Zeilenanzahl unbekannt (sed)

Beitrag von nihilist » 05.05.2011 05:03:33

Als erstes vielen Dank für deine sed Tipps. :THX:

Für das weitere vorgehen brauche ich etwas Zeit um zu überlegen wie ich vorgehe, bzw. mit welchem
"Kaliber" ich das file erlege :)

Kann also noch etwas dauern bis ich mich wieder hier melde.

nihilist
Beiträge: 430
Registriert: 27.04.2006 21:17:06
Kontaktdaten:

Re: Zeilen zusammenfügen wenn Zeilenanzahl unbekannt (sed)

Beitrag von nihilist » 15.06.2011 12:47:00

Ich hatte einen Ansatz mit python, verfolge das im Moment aber nicht weiter da mir ein Freund ein funktionierendes Skript in php geschrieben hat

Diese Seite ist daraus entstanden, bzw. wird entstehen, im Moment ist nur eine einfache Suchfunktion verfügbar.

Edit:
Bevor Fragen kommen, ich kenne http://packages.debian.org.
Da ich mich aber etwas mit Django beschäftigen möchte ist
das sozusagen mein Testprojekt. :)

Antworten