EMan: split Problem beim Auslesen von .txt Datenbanken

Hi Zusammen,

Ich habe eine Datenbank deren Werte über Doppelpunkte voneinander getrennt werden.

wert1:wert2:wert3:etc...

Nun möchte ich aber das auch innerhalb eines Werts ein Doppelpunkt stehen kann... z.b für URLs... also:

wert1:http://www.url.de:wert3:etc...

wie weiße ich das Script an den Doppelpunkt in der URL zu übergehen, also keinen split durchzuführen? Ist es vielleicht möglich diesen Doppelpunkt als anderes Zeichen zu tarnen und dann später im HTML Template wieder in einen Doppelpunkt umzuwandeln?
Ich weis das es nicht besonders sinnig ist Doppelpunkte als splits zu verwenden, aber andere Zeichen wie "&", "§", "%", kommen noch häufiger in der DB vor... und da diese DB schon gut 100 zeilen Inhalt umfasst, wäre es zu viel arbeit die splits jetzt noch zu ändern.

Nunja, ich hoffe das mir jemand helfen kann.

EMan

  1. Ich habe eine Datenbank deren Werte über Doppelpunkte voneinander getrennt werden.

    wert1:wert2:wert3:etc...

    Nun möchte ich aber das auch innerhalb eines Werts ein Doppelpunkt stehen kann... z.b für URLs... also:

    Datenbank ändern und bsp. im ".csv" -Format Speichern. Lässt sich auch unter Excel bearbeiten. Trennung der Werte dann durch (;)

    Dann kein Problem bei

    wert1;http://www.url.de;Beschreibung der URL

    wert2;etc...

    Gruß
    Andi

    1. Hi,

      Datenbank ändern und bsp. im ".csv" -Format Speichern. Lässt sich auch unter Excel bearbeiten. Trennung der Werte dann durch (;)

      oder vielleicht noch geschickter durch \t.

      Cheatah

  2. hi!

    wert1:http://www.url.de:wert3:etc...
    wie weiße ich das Script an den Doppelpunkt in der URL zu übergehen, also keinen split durchzuführen?

    Schwierig, da man im regulären Ausdruck in split ja nichts weiter unterscheiden kann (zb. benachbarte
    Zeichen), da alles weitere in diesem Ausdruck ja beim splitten einfach weggeworfen wird. Oder gibt es da
    eine Möglichkeit? Mir ist keine bekannt...

    Ist es vielleicht möglich diesen Doppelpunkt als anderes Zeichen zu tarnen und dann später im HTML
    Template wieder in einen Doppelpunkt umzuwandeln?

    Das ist möglich. Du brauchst nur ein eindeutiges Erkennungszeichen für den Doppelpunkt. Das können
    übrigens auch mehrere Zeichen sein, du die dann später ersetzt, zb. der String
      "andieserstellestehteigentlicheindoppelpunktdersplitaberfalschzuordnenwürde"
    Diesen String setzt du anstelle aller :-Zeichen in deiner Datenbank ein, die nicht als Trennzeichen zwischen
    den Feldern dienen sollen. Später kannst du dann über jeden Wert jedes Feldes folgende s/ubst/titu/tion
    laufen lassen:
      s/andieserstellestehteigentlicheindoppelpunktdersplitaberfalschzuordnenwürde/:/i;

    Ich weis das es nicht besonders sinnig ist Doppelpunkte als splits zu verwenden, aber andere Zeichen
    wie "&", "§", "%", kommen noch häufiger in der DB vor... und da diese DB schon gut 100 zeilen Inhalt
    umfasst, wäre es zu viel arbeit die splits jetzt noch zu ändern.

    Im regulären Ausdruck für split kann man auch einen komplexeren Ausdruck eingeben, der zum splitten
    verwendet werden soll, also nicht nur einzelne Zeichen. Du kannst zb. etwas in der Form verwenden:
      @(:)@
    Das setzt du einfach an Stelle aller Doppelpunkte, die als Trennzeichen gelten, in deiner Datenbank. Dann
    verwendest du zum splitten folgenden Aufruf:
      @liste = split /@\(:)\@/, $db_zeile;
    Reservierte Zeichen müssen natürlich maskiert werden. Eine Ersetzung aller Doppelpunkte in der Datei
    dürfte nicht so schwierig sein mit einem kleinen Perl-Skript oder auch einfach einem beliebigen Texteditor,
    der Suchen und Ersetzen beherrscht.

    Eine weitere Alternative: kommen nur in einem Feld zusätzliche Doppelpunkte vor, kannst du dieses Feld
    als letztes Feld verwenden. An split kann man als letzten Parameter einen Wert übergeben, wie viele
    Einzelwerte höchstens herauskommen sollen beim splitten.
      $db_zeile = "feld1:feld2:http://www.tower.de";
      @liste = split /:/, $db_zeile, 3;
    ergibt also für @liste folgende Werte:
      feld1, feld2 und http://www.tower.de

    bye, Frank!

  3. Moin!

    wie weiße ich das Script an den Doppelpunkt in der URL zu übergehen, also keinen split durchzuführen?

    Koennte mit einem *sehr* komplizierten regulaeren split-Ausdruck moeglich sein, besser waere aber:

    Ist es vielleicht möglich diesen Doppelpunkt als anderes Zeichen zu tarnen und dann später im HTML Template wieder in einen Doppelpunkt umzuwandeln?

    Eben dies. Beim Schreiben in die DB musst Du jeden Wert auf das :-Zeichen pruefen und dieses verschluesseln. Es kommt dann in den Werten selbst also nicht mehr vor. Als Verschluesselung bietet sich z.B. ein abgewandeltes URL-Encoding an, d.h. der Doppelpunkt wird durch %3A ersetzt (%-Zeichen gefolgt vom hexadezimalen ASCII-Code des Doppelpunkts). Da somit auch % eine Sonderbedeutung erhaelt, muss dieses ebenfalls codiert werden, am besten mit %25. Und das geht in Perl, indem Du auf *jeden* Wert, den Du in die DB schreibst, diesen regexp anwendest:

    s/([%:])/sprintf("%%%02X", ord($1))/eg;

    Dann steht in Deiner DB etwa

    wert1:http%3A//www.url.de:wert3:etc...
        
    Beim Auslesen machst Du die Codierung rueckgaengig, wie es bei jeder Docodierung von URL-encoded strings in CGI scripts getan wird, naemlich durch Anwenden von

    s/%([0-9A-Fa-f]{2})/chr(hex($1))/ge;
        
    auf *jeden* der ausgelesenen Werte.

    Ich weis das es nicht besonders sinnig ist Doppelpunkte als splits zu verwenden, aber andere Zeichen wie "&", "§", "%", kommen noch häufiger in der DB vor... und da diese DB schon gut 100 zeilen Inhalt umfasst, wäre es zu viel arbeit die splits jetzt noch zu ändern.

    Das macht ein Perl-Script von einer Zeile Umfang!

    So long, Calocybe

  4. Hallo Ihr alle!

    Nun möchte ich aber das auch innerhalb eines Werts ein Doppelpunkt stehen kann... z.b für URLs... also:

    wert1:http://www.url.de:wert3:etc...

    wie weiße ich das Script an den Doppelpunkt in der URL zu übergehen, also keinen split durchzuführen?

    Das ganze funktioniert mit einer "zero-width negative lookbehind assertion" :) Es wird nach hinten 'gen Anfang geschaut (lookbehind) ohne den entsprechenden Teilstring mit ins Ergebnis zu übernehmen (zero-width). Ausserdem soll der entsprechende Teilstring NICHT vorhanden sein (negative). Das ganze sieht dann so aus:

    split( /(?<!http):/, $datenzeile);

    Hat man mehrere Strings muss man auf die Länge achten, da in dieser Form der lookbehind eine fixe Länge haben muß. Hat man also mehrere Texte gleicher Länge, kann man sie per oder mit in die Klammer nehmen. Ansonsten gibt es halt noch eine Klammer. Zum Beispiel mal mit http, mail und ftp:

    split( /(?<!httpmail)(?<!ftp):/, $datenzeile);

    Viel Spaß,
       Jörk

    1. hi!

      Das ganze funktioniert mit einer "zero-width negative lookbehind assertion" :)
      split( /(?<!http):/, $datenzeile);

      Ich wusste, dass es diese Dinger gibt, aber ich wusste bis jetzt nur, wofür man (?:regex) gebraucht kann.
      Vielleicht sollte ich den entsprechenden Abschnitt in der Perl-Dokumentation doch nochmal durchlesen :)
      Das kann ja nicht angehen, dass du mir dauernd widersprichst... ;))

      bye, Frank!