Artikelliste auslesen

M

miami

Grünschnabel
Hallo an die Programmierer-Gemeinde,

ich hoffe ich bin hier richtig.
Ich hab ein Problem eine Artikelliste aufzulösen und getrennt zu speichern.
Sieht also so aus:
Bestehende Liste mit Daten in dem Format
100000;Name;Beschreibung;usw... nächste Zeile
100001;Name;Beschreibung;usw...
vor dem ersten Semikolon sind Artikelnummern, danach der Herstellername welche sich unterscheiden können.
Ich will nun den ersten Herstellernamen herausfinden, danach alle Zeilen die an der gleichen Position diesen Herstellernamen haben auslesen und in eine neue Datei speichern die diesen Herstellernamen tragen soll.
Danach sollen in der Ursprungsdatei alle diese kopierten Zeilen gelöscht werden und deer Vorgang soll wiederholt werden.
Soll also zum Schluss so aussehen das ich im besten Fall eine leere Ursprungsdatei habe und viel Dateien mit dem Herstellernamen und dem Inhalt der Artikel dieses Herstellers.

Ich hoffe es kann mir jemand helfen. Bin absoluter Neuling auf diesem Gebiet.

Im voraus schon mal Danke
 
Quick and dirty:

Code:
IFS=';'; cat file | while read a b c; do echo $a >> $b; done; unset IFS

Gruß, Xanti
 
Hallo Xanti,

erstmal vielen Dank für die schnelle Antwort.
Ich glaube ich hab mich falsch ausgedrückt bei meiner Beschreibng.
Dein code liefert mir verschieden Dateien mit den Artikelnummern.
Ich will jedoch den ganzen Zeileninhalt in neue Dateien schreiben.
Als Beispiel:
Muster der Ursprungsdatei:
1Zeile
1000001;Hersteller1;xyz;irgendetwas;stck
2Zeile
1000002;Hersteller2;xyz;irgendetwas;stck
.
.
.
.
87Zeile
1000087;Hersteller1;xyz;irgendetwas;stck

es kann also vorkommen das der gleich Hersteller in verschiedenen Zeilen vorkommt.

Muster neue Dateien:

Datei1
Dateiname=>Hersteller1.txt
1000001;Hersteller1;xyz;irgendetwas;stck
1000087;Hersteller1;xyz;irgendetwas;stck
.
.
.

Datei2
Dateiname=>Hersteller2.txt
1000002;Hersteller2;xyz;irgendetwas;stck
.
.
.

Ursprungsdatei zum Schluss leer zur Kontrolle

Gruß miami
 
in Perl

Soll also zum Schluss so aussehen das ich im besten Fall eine leere Ursprungsdatei habe und viel Dateien mit dem Herstellernamen und dem Inhalt der Artikel dieses Herstellers.
Hallo,

das mit dem Zeilen löschen verstehe ich noch nicht so ganz, denn wenn man fertig ist, kann man doch die Datei weg hauen?

Meine Version, in Perl:
Code:
#!/usr/bin/perl
$file = "liste.txt";
open(TABLE, "<$file") || die "$file not found!";
@lines_array = <TABLE>;
for(@lines_array){
    $line= "$_";
    @rows_split = split(/;/, $_);
    foreach($rows_split[1]){
 	open(NEW_TABLE, "[color=red]>>[/color]$_.txt");
	print NEW_TABLE $line;
    }
}

Ausgehend davon, daß hinter dem 1. Semikolon immer der Herstellername steht, und bei folgender Liste:
liste.txt schrieb:
100000;Mäckermünn;Toll;Test1
100001;CarStatt;besser;Test2
100002;Mäckermünn;Toll;Test3
100003;CarStatt;besser;Test4
100004;CarStatt;besser;Test5
100005;CarStatt;besser;Test6
100006;CarStatt;besser;Test7
hast du hinterher:
Mäckermünn.txt schrieb:
100000;Mäckermünn;Toll;Test1
100002;Mäckermünn;Toll;Test3
und:
CarStatt.txt schrieb:
100001;CarStatt;besser;Test2
100003;CarStatt;besser;Test4
100004;CarStatt;besser;Test5
100005;CarStatt;besser;Test6
100006;CarStatt;besser;Test7
 
Zuletzt bearbeitet:
Ok, hab das dann falsch verstanden. Kleine Änderung:

Code:
IFS=';'; cat file | while read a b c; do echo "$a;$b;$c" >> "$b"; done; unset IFS
 
Hallo Jens,

hab Dein Script mal gerade ausprobiert nd bekomme zwar dateien der verschiedenen Hersteller jedoch steht in jeder Datei nur eine Zeile,
muss jetzt mal überprüfen ob das immeer die erste Zeile ist in der der Hersteller vorkommt.

PS. Mit dem löschen hast Du recht. Die Datei kann eigentlich weg, war hlat nur zur Kontrolle gedacht ob alle Zeilen asgelesen werden.

Gruß miami
.
.
.
EDIT (autom. Beitragszusammenführung) :
.

Hallo Jens,

hab das jetzt mal überprüft, die Zeile in den Dateien ist die zuletzt vorkommende Zeile in der Ursprungsdatei.

Gruß miami
 
Zuletzt bearbeitet:
letzte Zeile

Code:
IFS=';'; cat file | while read a b c; do echo "$a;$b;$c" >> "$b"; done; unset IFS
Wenn die Liste nicht mit Zeilenumbruch endet, fehlt bei mir die letzte Zeile bzw. die Datei zur letzten Zeile....

Sowas ist natürlich 3x eleganter als ein Perl-Script, aber ich denke bei sowas immer gleich in Arrays... :O
.
.
.
EDIT (autom. Beitragszusammenführung) :
.

jedoch steht in jeder Datei nur eine Zeile
Da warst du schneller als ich mit dem Verbessern! Schaue mal auf die rot markierten ">>".... mit einfachem ">" wird immer die Datei mit dem jeweils aktuellen Wert überschrieben, aber mit ">>" immer angehängt.
 
Zuletzt bearbeitet:
Ja das hab ich auch gerade gesehen und ausprobiert.
Die Dateien werden jetzt geschrieben das ist schon mal super, mir ist nur aufgefallen das alle Umlaute weggelassen werden und die erste und letzte Zeile die gleichen sind.

Gruß miami
 
Zuletzt bearbeitet:
@Jabo: Naja, elegant ist meine Lösung bei Weitem nicht, eben quick and dirty. ;)

@miami: Füge

Code:
use utf8;

direkt unter der shebang (#!/usr/bin/perl) ein.
 
und die erste und letzte Zeile die gleichen sind.
Hallo,

also das passiert bei mir nicht! Ich nutze lokal utf8 nicht, deshalb hatte ich das Problem mit den Umlauten nicht, aber doppelte Zeilen? Deshalb hatte ich in meinem Beispiel hinten "Testn" stehen und "n" fortlaufend nummeriert. Ich hatte beim Test keine doppelten Nummern / Zeilen....

Das Script checkt aber auch nicht, ob im Array was doppelt ist, das kann man natürlich auch.
 
Sorry war mein Fehler, hätte die zuerst erzeugten Dateien löschen müssen.
So wurden die Dateien nur geöffnet und alles an die zuerst erzeugte Zeile vom ersten Probelauf angehängt.
Hab jetzt alle Dateien mal gelöscht und nochmal probiert dann klappts, nur der Fehler mit den Umlauten besteht noch, obwohl ich "use utf8;" eingefügt habe.

Gruß miami
 
So wurden die Dateien nur geöffnet und alles an die zuerst erzeugte Zeile vom ersten Probelauf angehängt.
Ah, ok.... aber wenn man das öfter macht, könnte noch eine Zeile rein, die jede Datei immer leer anlegt, bevor die Schleife dann was dranhängt. Dran hängen muß die Schleife halt, sonst s.u. ...

der Fehler mit den Umlauten besteht noch, obwohl ich "use utf8;" eingefügt habe.
Wie sind sie denn im Original kodiert? Sonst fällt mir im Moment nix ein. Wenn man einfach das macht:
Code:
#!/usr/bin/perl
$file = "liste.txt";
open(TABLE, "<$file") || die "$file not found!";
@lines_array = <TABLE>;
for(@lines_array){
    print $_;
}
wie werden sie von Perl denn dann ausgegeben? In "$_" steht immer eine Zeile in dem Moment, wie sie geschrieben werden würde, die muß ja dann schon kaputt sein?!?

Außerdem fällt mir gerade auf, daß ich die geöffneten Dateien nicht schließe, aber das Script endet ja, bevor das stört ... :O
 
Hab das Script mal getetstet, dann werden die Umlaute auch nicht ausgegeben.
Hab das Problem jetzt aber gefunden.
Gar nicht so einfach durch mehrere 100000 Artikel zu scrollen.
Die Umlaute sind in der Datei schon garnicht drin. Wahrscheinlich ist da beim Grosshändler beim auslesen schon was schiefgegangen.
Zu dem Vorschlag mit der leeren Zeile.
Das ist eigentlich nicht nötig da die Dateien nachdem sie dann einzeln eingelsen wurden sowieso gelöscht werden.
Der Vorgang wird immer nur mit einer neuen Ursprungsdatei gestartet,
danach die einzelnen Dateien eingelesen und dann gelöscht.
Scheint also so zu funktionieren.
Also vielen, vielen Dank Ihr habt mir sehr geholfen.
Ich hoffe ich hab nicht zuviel genervt

Gruß miami
 
Ich muss mich nochmal melden.
Beim durchsehen der erstellten Textdateien hab ich festgestellt dass der Herstellername der abgefragt wird scheinbar nicht in allen Datensätzen gr0ss geschrieben ist und daher werden dann auch unterschiedliche Textdateien angelegt. 1mal gross geschrieben und einmal klein.
Gibt es eine Möglichkeit zuerst alle Herstellernamen in Grossbuchstaben umzuwandeln und dann erst die Dateien zu erzeugen.

Gruß;
miami
 
Soll der Name nur im Filenamen grossgeschrieben werden:

Code:
#!/usr/bin/perl -w                                                                                                                                                                                                 
$file = "liste.txt";
open(TABLE, "<$file") || die "$file not found!";
@lines_array = <TABLE>;
for(@lines_array) {
   $line = $_;
   @rows_split = split(/;/, $line);
   $rows_split[1] =~ tr/[a-z]/[A-Z]/;                                                                                                                                                                              
   foreach($rows_split[1]) {
      open(NEW_TABLE, ">>$_.txt");
      print NEW_TABLE $line;
   }
}

oder auch in der Zeile:

Code:
#!/usr/bin/perl -w                                                                                                                                                                                                 
$file = "liste.txt";
open(TABLE, "<$file") || die "$file not found!";
@lines_array = <TABLE>;
for(@lines_array) {
   $line = $_;
   $line =~ s/(;[^;]*?;)/uc $1/e;                                                                                                                                                                                  
   @rows_split = split(/;/, $line);
   foreach($rows_split[1]) {
      open(NEW_TABLE, ">>$_.txt");
      print NEW_TABLE $line;
   }
}
 
Die zweite Version ist das was ich suche.
Wird komplett ausgeführt jedoch kommt noch eine Fehlermeldung.

print() on closed filehandle NEW_TABLE at ./Artikelkonvertierung2 line 11, <TABLE> line 127806.

Was aber die Ausführung anscheinend nicht stört.
Klappt super. War genau das was ich gesucht habe.
Nochmals vielen Dank

Gruß,
miami
 
Wenn es eine Fehlermeldung wäre, würde das Skript nicht durchlaufen. Es ist eine Warnung (eingeschaltet durch #!/usr../perl -w), die wahrscheinlich zustandekommt, weil NEW_TABLE nicht geschlossen wird. Ausserdem ist mir eben noch aufgefallen, dass die zweite foreach-Schleife unnötig ist, da es sich nicht um eine Liste handelt:

Code:
#!/usr/bin/perl -w                
use strict;                                                                       
my $file = "liste.txt";
open(TABLE, "<$file") || die "$file not found!";
foreach (<TABLE>) {
   s/(;[^;]*?;)/uc $1/e;
   my @rows_split = split(/;/, $_);
   open(NEW_TABLE, ">>$rows_split[1].txt");
   print NEW_TABLE $_;
   close NEW_TABLE;
}
close TABLE;
 
Zuletzt bearbeitet:

Ähnliche Themen

Prblem mit zeilenweises auslesen von Datei und schreiben nach mysql

Bash Skript: [[: not found Fehler

Last mit etc/passwd anzeigen lassen

[HowTo] Debian Installation mit Installer über SSH

Knobelaufgabe für UNIX Könner (und Hilfe für einen N00b)

Zurück
Oben