staging.inyokaproject.org

Datensatz mit der Shell konvertieren

Status: Gelöst | Ubuntu-Version: Lubuntu 16.04 (Xenial Xerus)
Antworten |

Wutze

Anmeldungsdatum:
16. November 2009

Beiträge: Zähle...

Hallo zusammen,

ich bräuchte mal bitte eure Hilfe.

Ich habe einen Datensatz mit rund 300.000 Zeilen als reine Textdatei. Die einzelnem Datensätze, zeilenweise angelegt, besitzen alle eine konstante Länge. Das Datenschema (siehe Beispiel) ist demnach klar. Nun möchte ich die Daten trennen und auf mehrere Tabellen einer Datenbank verteilen. Das ganze würde ich gern per Shellscript auf der Konsole machen, statt mit php, was mir wesentlich geläufiger wäre.

Hat jemand bitte einen Denkansatz, damit ich zumindest einen Anfang finde?

Danke

000000000001167400839105090700000479SEITENB TROPIC MUESLI                      BT 43881109000500000000000000002772
+--------1----++---2-------++3-----++------------4---------5---------6-------++7-++------8+--++---9---------10+--+
123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234

001-015 Artikelnummer
016-028 Referenznummer 
029-036 VK Preis 6 Vorkomma und 2 Nachkommastellen
037-068 Artikelbezeichnung
069-072 Gebindeart
073-080 Lieferantennummer
081-084 Gebindeinhalt
085-100 unbenutzt
101-104 Warengruppe

Seebär

Avatar von Seebär

Anmeldungsdatum:
2. Mai 2009

Beiträge: 833

  • mit read zeilenweise einlesen

  • zeile dann in parameter splitten, ist ja stellentreu (wie man in der bash splittet findest du sicher über passende manuals oder schnell via stackoverflow raus)

  • 2. script "doSQLstuff" $artikelnummer $referenznummer ... aufrufen (und erstellen), da dann den SQL-Zinober ggf auch Validierung machen und falsche Daten in badfile parken.

Nebenbei: deine "Spaltenzählerzeile" ist ziemlich falsch.

schusch

Avatar von schusch

Anmeldungsdatum:
2. September 2008

Beiträge: 324

Ich würde mir mit awk die entsprechenden sql-Befehle erzeugen.

Etwa so:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
< EinagebeDatei awk 'BEGIN {
    printf("<Befehl zum anmelden an der Datenbank>\n")
}
{
  anr=substr($0,1,15)
  ref=substr($0,16,12)
  ...
  wgr=substr($0,101,4)
  # <if oder switch zum festlegen des tabellen namens = tblnam>
  
  printf("insert into %s (artnr, ref, ..., wgr) values (%s, %s, ...,%s);\n", tblnam, anr, ref, ... , wgr)
}
END {
  printf ("commit;\nquit;\n")
}'

track

Avatar von track

Anmeldungsdatum:
26. Juni 2008

Beiträge: 7174

Je nachdem wie die weitere Verarbeitung aussieht, würde ich wahrscheinlich auch awk nehmen, wie von schusch vorgeschlagen.

Sonst, wenn Du die DB-Befehle sowieso in einem Shellskript ausführst, ginge die Zerlegung auch mit einer Reihe Parameter Expansions:

1
2
3
4
5
6
7
8
9
while read z ; do
    art=${z:1:15}
    ref=${z:16:12}
    vk=${z:29:7}
    bez="${z:37:32}"
    # usw.   (aber Deine Zählung stimmt ab hier nicht mehr)

    # und hier kämmen dann die DB-Befehle
done  <  datensatz.txt

Im Gegensatz zu awk ö.Ä. kennt die Shell keine Dezimalzahlen. (nur Integer !) Die Kommatrennung müsstest Du also in der DB auffangen.

LG,

track

user_unknown

Avatar von user_unknown

Anmeldungsdatum:
10. August 2005

Beiträge: 17630

Oft haben die Datenbanken selbst Importfunktionen oder fertige Programme, um rohe Daten zu importieren.

Wenn nicht, können sie oft CSV-Daten importieren.

1
2
echo 000000000001167400839105090700000479SEITENB TROPIC MUESLI | sed -r 's/^(.{15})(.{13})(.*)/\1;\2;\3/'
000000000001167;4008391050907;00000479SEITENB TROPIC MUESLI

(nur für die ersten 2 Spalten implementiert).

Mich irritiert, dass Du es auf mehrere Tabellen verteilen willst. Normalerweise bringt man die Dateien in die 3. Normalform, so dass ein Datensatz eine funktionale Abhängigkeit vom Primärschlüssel hat. Wenn hier eine Zeile in verschiedene Tabellen soll, dann müsste man mehr dazu wissen. Am bequemsten dürfte aber sein, erst mal alles in eine Datenbanktabelle zu schreiben, und von dort dann, bei Bedarf, mit SQL auf mehrere zu verteilen.

OpenOffice kann übrigens auch Spalten nach Position trennen, aber Du hattest ja nach Kommandozeile gefragt, und von LO-Calc zur Datenbank ist auch kein trivialer Weg.

kB Team-Icon

Supporter, Wikiteam
Avatar von kB

Anmeldungsdatum:
4. Oktober 2007

Beiträge: 9837

Für die Auswahl von Teilen der Datenzeilen gibt es das Kommandozeilenprogramm cut. Bei Datenfeldern fester Länge wie hier nimmt man, je nach Codierung der Zeichen in Bytefolgen, entweder die Option -b oder -c. Lies:

1
man cut

Beispielsweise würde

1
cut -c1-15,101-104 EINGABEDATEI

nur die Artikelnummer und die Warengruppe übertragen. Verwende keine führenden Nullen, manchmal zeigen diese Oktalzahlen an.

Wutze

(Themenstarter)

Anmeldungsdatum:
16. November 2009

Beiträge: 364

Danke euch allen, ihr seid mir eine große Denkhilfe gewesen ;o)

@unknown - es sind mehrere Datensätze, deswegen schrieb ich "auf mehrere Tabellen verteilen". Sorry, war ne Ungenauigkeit von mir.

@Track - ich habe die Original-Doku hier her kopiert. Beim spielen mit dem Datensatz fiel mir dann auch auf, dass die Länge irgendwie nicht mehr passte.

@kB - das mit den führenden Nullen wird sicher noch ein Problem, wenn ich Pech habe. Jedoch hat die Original-Datenbank tatsächlich immer die selbe Feldlänge und alles wurde mit Nullen gefüllt.

Danke auf jeden Fall, ich habe einen Ansatz. Wenn ich den fertig habe, werde ich es hier mal "zeigen". Im Moment habe ich es erst mal ganz simpel per LibreOffice und CSV gemacht, um zumindest die Datenbank und das aufteilen der ganzen Daten zu testen.

Antworten |