Ralf: Komplizierte Textdatei in MySQL umwandeln

Ich muss dringend eine Wörterbuchdatei in MySQL umwandeln, scheitere aber an der Unregelmäßigkeit der Datei.

Ich versuche einmal, die Deutsch-Englisch-Japanisch Datei zu beschreiben:
Am Zeilenbeginn steht ein dt. Ausdruck, dann ein Trennzeichen und  kein bis mehrere engl. Ausdruck, die mit (E) beginnen, dann min. ein jap Ausdruck, der mit (J) beginnt, alles immer mit dem "|" getrennt:

aaaaa|(E)bbbbb|(E)ccccc|(J)xxxxx|(J)yyyyy

Idealerweise sollten drei Spalten entstehen, für jede Sprache eine, die auch mehrere Ausdrücke enthalten kann.

Wie kann man soetwas lösen? Explode alleine hilft ja nicht....

Danke für eure Hilfe!

  1. Hi,

    Datei und Gesetze der Unregelmäßigkeiten sind IMHO gar nicht so kompliziert. Ein Lösungsweg (ohne große Vorüberlegung) könnte sein:

    • Zeilenweise (Datei)
        - Zeile anhand des Trennzeichens | aufsplitten
        - Element-Weise (Splitt-Array)
          - mit regulärem Ausdruck (oder einfach Str-Fnkt.) auf kein (.) (E) und (J) prüfen und Elemente entsprechend in Hilfs-Array kopieren
          - drei Strings aus Hilfs-Array (Unterstrings jew. getrennt durch z.B. |) erzeugen und in DB-Tab schreiben

    MfG
    Danny

    1. Danke Danny!

      Ich bin leider noch nicht ganz vertraut mit PHP, könntest du mir bitte einige Details nennen?
      Vor allem das Splitten, Abfragen und die Hilfs-Arrays.
      Vor einiger Zeit hatte ich mit folgendem Skript Erfolg, die Quelldatei war aber eindeutig getrennt:

      <?php
      set_time_limit(7200);
      mysql_connect("localhost", "root", "");
      mysql_select_db("wadoku");
      $quelle = file ('./wadoku.txt');

      for($i=0; $i<sizeof($quelle); $i++) {
            $line = trim($quelle[$i]);
            $arr = explode(";", $line);

      $sql = "insert into wadoku values ('".
                        implode("','", $arr) ."')";
            mysql_query($sql);
            echo $sql ."<br>\n";
            if(mysql_error()) {
               echo mysql_error() ."<br>\n";
            }
      }
      ?>

      Danke vielmals!
      ralf

      1. Hallo Ralf,

        Ich bin leider noch nicht ganz vertraut mit PHP, könntest du mir bitte einige Details nennen?
        Vor allem das Splitten, Abfragen und die Hilfs-Arrays.
        Vor einiger Zeit hatte ich mit folgendem Skript Erfolg, die Quelldatei war aber eindeutig getrennt:

        <?php
        set_time_limit(7200);
        mysql_connect("localhost", "root", "");
        mysql_select_db("wadoku");
        $quelle = file ('./wadoku.txt');

        for($i=0; $i<sizeof($quelle); $i++) {
              $line = trim($quelle[$i]);
              $arr = explode(";", $line);

        an dieser Stelle wieder eine Schleife:
        foreach($arr as $item)
        {
           wenn am Anfang (E) steht, arr_englisch[]=$item;
           sonst, wenn (J) am Anfang, arr_japsisch[]=$item;
           sonst arr_germanisch[]=$item;
        }

        Gruß, Andreas

        --
        <img src="http://was-ist-das.andreas-lindig.de/was_ist_das_fetzen.jpg" border="0" alt="">
        hier könnte auch ruhig mal'n neues Bild stehen.
  2. Hello,

    für jeden Datensatz des Wörterbuches

    $_sprache = explode("|","aaaaa|(E)bbbbb|(E)ccccc|(J)xxxxx|(J)yyyyy";

    ergibt ein Array mit

    [0] => 'aaaaa'

    [1] => '(E)bbbbb'

    [2] => '(E)ccccc'

    [3] => '(J)xxxxx'

    [4] => '(J)yyyyy'

    ...

    Nun muss man die Begriffe "nur noch" in drei Tabellen verteilen:

    $deutsch = $_sprache[0];
    unset $_sprache[0];  ## deutschen Arrayeintrag beseitigen

    $sql = "insert into DEUTSCH set begriff = '$deutsch'";
    $ins = mysql_query($sql,$con);
    $lid = mysql_insert_id($con);

    foreach($_sprache as $begriff)
    {
      if (substr($begriff,0,3)==(E))
      {
        ## englischer Eintrag
        $sql = "insert into ENGLISCH set ".
               "id_deutsch = $lid,".
               "begriff = '$begriff'";
        $ins = mysql_query($sql,$con);
      }
      elseif (substr($begriff,0,3)==(J))
      {
        ## japanischer Eintrag
        $sql = "insert into JAPANISCH set ".
               "id_deutsch = $lid,".
               "begriff = '$begriff'";
        $ins = mysql_query($sql,$con);
      }
      else
      {
        ## sonstiger Eintrag
        $sql = "insert into PRUEFEN set ".
               "id_deutsch = $lid,".
               "begriff = '$begriff'";
        $ins = mysql_query($sql,$con);
      }
    }

    Idealerweise sollten drei Spalten entstehen, für jede Sprache eine, die auch mehrere Ausdrücke enthalten kann.

    bitteschön.

    Liebe Grüße aus http://www.braunschweig.de

    Tom

    --
    [ Computer-Camp für PHP-Anwender in den Sommerferien. Programmieren,
      Sport, Fun, Fete. Teilnehmermindestalter Gruppe 1: 14 Jahre
      Mindestalter Gruppe 2+3 18 Jahre, Info bei mir ]
    Fortschritt entsteht nur durch die Auseinandersetzung der Kreativen
  3. Hallo Ralf,

    Am Zeilenbeginn steht ein dt. Ausdruck, dann ein Trennzeichen und  kein bis mehrere engl. Ausdruck, die mit (E) beginnen, dann min. ein jap Ausdruck, der mit (J) beginnt, alles immer mit dem "|" getrennt:
    aaaaa|(E)bbbbb|(E)ccccc|(J)xxxxx|(J)yyyyy

    du hast Glück - das hat mich interessiert, ob das mit einem regulären Ausdruck zu lösen ist :-)
    Nach einigem Probieren habe ich dann eine Lösung gefunden, allerdings musste das was der reguläre Ausdruck ausspuckt erst noch weiterverarbeitet werden, um die einzelnen Wörter zu erhalten:

    /*
      Funktion: sucheSprachen
      Parameter: string - der zu zerteilende String
                 sprachen - ein Array mit den Sprachen in der Form:
                     <Kürzel zwischen den Klammern> => '<sprachkürzel>'
                    z.B. also: array('E'=>'en','J'=>'jp')
                    die Sprachen müssen allerdings in der Reihenfolge angegeben werden wie
                    sie auch im String vorkommen, sonst wird nur die letzte Sprache gefunden
      Rückgabe: ein Array mit:
        - dem deutschen String ($rueckgabe['de'])
        - je einem Array mit der enthaltenen Sprache (im Beispiel: $rueckgabe['en'] u. $rueckgabe['jp'])
    */
    function sucheSprachen($string,$sprachen){
      //evtl. vorhandene Leerzeichen und Zeilenumbrüche entfernen
      $string = trim($string);
      //Beginn des regulären Ausdrucks (s.u.)
      $regexpr = '~(.*?)|';
      //das Array $sprachen wird durchlaufen und für jedes Kürzel wird der reguläre Ausdruck ergänzt
      foreach($sprachen as $klammer => $kuerzel){  //->http://www.php.net/foreach
        $regexpr .= '((?:('.$klammer.')[^|]*[|]?)+)?';
      }
      //Ende des regulären Ausdrucks
      $regexpr .= '~';
      /*
      wenn die Funktion mit array('E'=>'en','J'=>'jp') aufgerufen wird, sieht der
      generierte reguläre Ausdruck dann so aus:
        ~^(.*?)|((?:(E)[^|]*[|]?)+)?((?:(J)[^|]*[|]?)+)?$~
      damit er etwas übersichtlicher wird (und zum Erklären), habe ich mal ein
       paar Zeilenumbrüche eingebaut:

    ~^  # Beginn des regulären Ausdrucks mit Anker für den Beginn des Strings
      (.*?)|  #findet den deutschen Ausdruck mit einem | dahinter
      (          # Beginn der Speicherung der englischen Ausdrücke
        (?:      # mit der Klammer werden die einzelnen Wörter gefunden, das '?:' ist dafür da,
                 #  dass das der Treffer nicht gespeichert wird
           (E) # findet das '(E)'
           [^|]* # findet alle Zeichen außer | (was ja das Ende des Wortes markiert)
           [|]?  # findet das | (optional weil am Ende des Strings kein | mehr steht)
        )+       # Ende des Bereiches für die einzelnen Wörter, muss mindesten einmal gefunden werden
      )?         # Ende der Speicherung der englischen Ausdrücke (optional, um Fehler zu vermeiden,
                 #  wenn in $sprachen eine Sprache angegeben ist, die in $string nicht vorkommt)
      ((?:(J)[^|]*[|]?)+)?  # das gleiche wie für die englischen Teile
      $~  # Ende des regulären Ausdrucks mit Anker für den Ende des Strings
      */
      //wendet den regulären Ausdruck auf $string an, und speichert die Treffer in $match
      preg_match($regexpr,$string,$match);  //->http://de3.php.net/preg_match
      //speichert den deutschen Treffer im Rückgabearray
      $ergebnis['de'] = $match[1];
      //löscht die ersten zwei Elemente von $match (der gesamte String, und der deutsche Treffer)
      unset($match[0]);
      unset($match[1]);
      foreach($match as $sprache){
        //sucht sich das Kürzel, dass in den Klammern steht
        $temp = substr($sprache,1,1);  //->http://de3.php.net/substr
        //speichert den Sprachenstring zusammen mit mit dem Kürzel als Key in $match2
        $match2[$temp] = $sprache;
      }
      foreach($match2 as $sprache => $woerter){
        //löscht evtl. vorhandene | aus dem "Sprachenstring" und auch gleich das führende '(E)'
        $woerter = str_replace('|','',substr($woerter,strlen($sprache)+2));
        //teilt das ganze an '(E)' (bzw. '(J)') auf und speichert das ganze im Rückgabearray
        $ergebnis[$sprachen[$sprache]] = explode('('.$sprache.')',$woerter);
      }
      //und das Ergebnis noch zurückgeben
      return $ergebnis;
    }

    das ganze mit den Parametern:
      $zeile = 'aaaaa|(E)bbbbb|(E)ccccc|(J)xxxxx|(J)yyyyy';
      $sprachen = array('E'=>'en','J'=>'jp');
    und dem funktionsaufruf:
    $ergebnis = sucheSprachen($zeile,$sprachen);
    aufgerufen, gibt dann mit
      print_r($ergebnis);
    dieses Ergebnis:

    Array
    (
      [de] => aaaaa
      [en] => Array
        (
          [0] => bbbbb
          [1] => ccccc
        )
      [jp] => Array
        (
          [0] => xxxxx
          [1] => yyyyy
        )
    )

    • alle Klarheiten beseitigt? :-)

    Bei Fragen, Fehlern o.ä. einfach nochmal posten

    Grüße aus Nürnberg
    To*bittenichtschlagenweilicheinevollständigelösunggepostethabe*bias

    --
    Selfcode: sh:( fo:) ch:? rl:( br:< n4:& ie:% mo:| va:) de:] zu:) fl:( ss:| ls:[ js:|