Otto Wyss: Mehrfaches ersetzen mit Regex

Nachdem ich mich nun längere Zeit mit Umlauten in Dateinamen herumgeärgert habe, habe ich mich nun für die Holzhammermethode entschlossen ("ä"=>"a_", "ö"=>"o_", "ü"=>"u_"). Im Client ersetze ich die Zeichen für die Darstellung zurück mittels

f = f[1].replace(/a_/g, 'ä').replace(/o_/g, 'ö').replace(/u_/g, 'ü');

Gibt es da eine bessere Lösung mit nur einem "replace"?

  1. Tach!

    f = f[1].replace(/a_/g, 'ä').replace(/o_/g, 'ö').replace(/u_/g, 'ü');
    Gibt es da eine bessere Lösung mit nur einem "replace"?

    Mir fällt da nur eine mit einem Array und einer for-Schleife ein. Dadurch wird es jedoch erst ab sagen wir mal 5 Ersetzugen wartungsärmer.

    Das Problem ist ja schon, wie das Suchmuster zu definieren wäre. Du willst ja nicht nacheinander stehende Zeichen suchen, sondern irgendwo das a_ und irgendwo das o_ und irgendwo das u_. Also kannst du nur diese drei Zeichen mit einem Oder verknüpft suchen. Und dann musst du im Ersetzungsteil unterscheiden, welches der drei Zeichen du hast und entsprechend ersetzen. Das geht zwar auch mit einer Funktion, darin dann aber mit einem switch oder geschachtelten if. So wird es jedenfalls nicht einfacher.

    dedlfix.

    1. Das Problem ist ja schon, wie das Suchmuster zu definieren wäre. Du willst ja nicht nacheinander stehende Zeichen suchen, sondern irgendwo das a_ und irgendwo das o_ und irgendwo das u_.

      Genau, das ist das Problem. Die Laufzeit ist kein Problem, da es sich um eine kleine Menge von Daten handelt. Aber vielleicht kennt sich jemand besser mit Regex (Javascript) aus als ich. So mehrere "replace" hintereinander sehen doch etwas komisch aus.

      1. Tach!

        So mehrere "replace" hintereinander sehen doch etwas komisch aus.

        Es sähe wesentlich komplizierter aus, einen Ausdruck zu schreiben, der mehrere Dinge gleichzeitig suchen und dann noch unterschiedlich behandeln soll. Zudem gibt es keine RegExp-Syntax, die so etwas tut. Was du suchst, wäre das Äquivalent zur zweiten Variante von PHPs strtr()-Funktion. Das gibt es zwar in einer Javascript-Variante, aber einfacher als drei replace() wird es durch die zusätzliche Funktion auch nicht.

        dedlfix.

  2. Hallo,

    Nachdem ich mich nun längere Zeit mit Umlauten in Dateinamen herumgeärgert habe, habe ich mich nun für die Holzhammermethode entschlossen ("ä"=>"a_", "ö"=>"o_", "ü"=>"u_"). Im Client ersetze ich die Zeichen für die Darstellung zurück ...

    ich würde stattdessen eher empfehlen, die Ursache dieser Problematik zu finden und zu bekämpfen, anstatt Workarounds zu stricken. Du verwendest anscheinend unterschiedliche Zeichencodierungen innerhalb deines Projekts, und das rächt sich hier. Analysiere das, und verwende dann konsequent nur noch eine einheitliche Codierung.

    Abgesehen davon: Meinst du wirklich _Datei_namen? Vermutlich nicht. Javascript hat, von wenigen Ausnahmen abgesehen, nichts mit Dateien im Sinn. Vermutlich meinst du HTTP-Ressourcen. Dann allerdings sind Umlaute (und alle anderen Nicht-ASCII-Zeichen) generell problematisch, weil das Protokoll keine Möglichkeit vorsieht, die verwendete Codierung anzugeben - abgesehen davon, dass natürlich alle Nicht-ASCII-Zeichen (und sogar ein paar aus dem ASCII-Bereich) URL-codiert werden müssen.
    Hier fährt man also am besten, wenn man Umlaute von vornherein vermeidet.

    Ciao,
     Martin

    --
    "Drogen machen gleichgültig."
     - "Na und? Mir doch egal."
    Selfcode: fo:) ch:{ rl:| br:< n4:( ie:| mo:| va:) de:] zu:) fl:{ ss:) ls:µ js:(
    1. ich würde stattdessen eher empfehlen, die Ursache dieser Problematik zu finden und zu bekämpfen, anstatt Workarounds zu stricken.

      Würde ich ja gerne, aber scheinbar geht es nicht, mit meinen beschränkten Kenntnissen.

      Abgesehen davon: Meinst du wirklich _Datei_namen?

      Ja ich meine Dateinamen. Ich lese mit einem PHP-Script Verzeichnisse und Dateien aus und wandle sie für die Anzeige mit utf8_encode. Wenn ich jedoch damit ein Adress-Element bilde, wird die Datei nicht gefunden. Ich müsste auf dem Client wieder zurückwandeln können, aber das scheint leider nicht einfach möglich zu sein.

      Ich habe auch schon versucht, den Dateinamen als "iso" und "utf8" zu übergeben, aber das verträgt PHP nicht, wenn man das in einem String über den Operator "." macht. Aber wenn du eine gute Lösung hast, probiere ich sie gerne aus.

      Auch schon über assoziatives Array habe ich es versucht (Filename als Index), nur schaffe ich es nicht, auf dem Client den Index wieder richtig auszulesen.

      Hier fährt man also am besten, wenn man Umlaute von vornherein vermeidet.

      Das steht leider nicht zur Debatte, da die Namen eben "äöü" enthalten können. Ausser eben meine Lösung vermeidet Umlaute komplett.

      Da es sich um jpg-Dateien handelt, könnte man zwar den echten Namen in den Tags unterbringen, nur wie liest man diese mit Javascript im Client wieder aus.

      Vielleicht gibt es noch andere Möglichkeiten, aber dann müsste ich schon ein funktionierendes Beispiel sehen.

      1. Tach!

        Ich lese mit einem PHP-Script Verzeichnisse und Dateien aus und wandle sie für die Anzeige mit utf8_encode. Wenn ich jedoch damit ein Adress-Element bilde, wird die Datei nicht gefunden. Ich müsste auf dem Client wieder zurückwandeln können, aber das scheint leider nicht einfach möglich zu sein.

        Das Problem hört ja nicht bei äöü nebst ÄÖÜ und ß auf. Für die Anzeige kannst du ja utf8_encode() nehmen. Wenn du diese Funktion verwenden musst, um Umlaute richtig angezeigt zu bekommen, scheint es so, dass dein Dateisystem ISO-8859-1 liefert. Leider ist nicht festgelegt, welche Kodierung das Dateisystem verwendet, und mir ist auch keine Abfragemöglichkeit bekannt. Da PHPs Stringfunktionen aber byteweise arbeiten, ist das eigentlich auch egal. Um den Dateinamen zu erhalten (im Sinne von konservieren), so wie er kommt, solltest du urlencode() oder rawurlencode() anwenden, bevor du daraus eine Adresse bildest. Dann hast du nur noch ASCII und nichts sollte verloren gehen. - Wenn dieses Adress-Element wieder zurück zum Server geschickt wird, dekodiert PHP von selbst die URL-Kodierung, und du solltest wieder in die Bytefolge erhalten, die du aus dem Dateisystem gelesen hast.

        dedlfix.

      2. Hallo,

        Abgesehen davon: Meinst du wirklich _Datei_namen?
        Ja ich meine Dateinamen. Ich lese mit einem PHP-Script Verzeichnisse und Dateien aus ...

        okay, dieser Teil ist damit klar. Und er birgt schon den ersten Teil des Problems: Du weißt vermutlich nicht, in welcher Codierung Dateinamen auf deinem Server vorliegen.
        Normalerweise würde ich da heutzutage UTF-8 erwarten. Muss aber nicht zwangsläufig so sein.

        ... und wandle sie für die Anzeige mit utf8_encode.

        Dann solltest du aber sicher sein, dass sie nicht sowieso schon in UTF-8 vorliegen. Gib mal im PHP-Script probehalber einen der gefundenen Dateinamen mit Umlaut mit

        echo urlencode($name);

        aus. Achte darauf, ob für den Umlaut ein oder zwei Bytes angezeigt werden. Sind es zwei, hast du mit nahezu 100% Wahrscheinlichkeit UTF-8; ist es nur eins, dann ist es eine der gängigen Single-Byte-Codierungen, z.B. ISO-8859-1. Dann und nur dann ergibt die Umwandlung mit utf8_encode() einen Sinn, und natürlich auch nur, wenn das zum Client ausgelieferte Dokument insgesamt auch UTF8-codiert ist.

        Wenn ich jedoch damit ein Adress-Element bilde, wird die Datei nicht gefunden. Ich müsste auf dem Client wieder zurückwandeln können, aber das scheint leider nicht einfach möglich zu sein.

        Ich beginne so langsam, dein Problem zu verstehen. Glaube ich jedenfalls. ;-)
        Und ich würde für den Lösungsansatz komplett von Javascript weggehen und die Geschichte rein serverseitig (z.B. in PHP) abfrühstücken.

        Du musst zwei Dinge unterscheiden, wenn du Namen mit Nicht-ASCII-Zeichen verarbeitest. Die korrekte Anzeige beim Client, und die korrekte Codierung des Links (bzw. des src-Attributs, wenn es um Bilder geht), wenn daraus wieder ein Request an den Server werden soll.

        Ersteres kannst du mit dem oben genannten Test leicht hinkriegen. Letzteres auch - in den URLs sollte schon gar kein Nicht-ASCII-Zeichen mehr auftauchen. Du solltest also im Script die gefundenen Namen erst mit utf8_encode() umwandeln, falls sie noch nicht UTF-8 sind. Das ergibt den String, der für die Anzeige verwendet wird. Um ihn in URLs einzusetzen, solltest du ihn dann noch mit urlencode() codieren:

        $name = utf8_encode($filename);  
        echo "<a href='" . urlencode($name) . "'>$name</a>";
        

        Ich habe hier im Beispiel bewusst ein a-Element verwendet und kein img-Element, damit der Unterschied zwischen angezeigtem Namen und URL deutlicher wird.

        Ich habe auch schon versucht, den Dateinamen als "iso" und "utf8" zu übergeben, aber das verträgt PHP nicht, wenn man das in einem String über den Operator "." macht.

        Das verstehe ich nun wieder nicht.

        Da es sich um jpg-Dateien handelt, könnte man zwar den echten Namen in den Tags unterbringen, nur wie liest man diese mit Javascript im Client wieder aus.

        AFAIK hat Javascript keine Möglichkeit, auf diese Metainformationen in JPEG-Grafiken zuzugreifen.

        So long,
         Martin

        --
        Auch mit eckigen Radios kann man Rundfunk hören.
        Selfcode: fo:) ch:{ rl:| br:< n4:( ie:| mo:| va:) de:] zu:) fl:{ ss:) ls:µ js:(
        1. Normalerweise würde ich da heutzutage UTF-8 erwarten. Muss aber nicht zwangsläufig so sein.

          Leider nein, es ist ein ISO-8859-1

          ... und wandle sie für die Anzeige mit utf8_encode.

          Das machte ich bereits.

          echo urlencode($name);

          Hatte ich auch schon gemacht, allerdings ohne "urlencode". Daran habe ich bis jetzt nicht gedacht.

          Du musst zwei Dinge unterscheiden, wenn du Namen mit Nicht-ASCII-Zeichen verarbeitest. Die korrekte Anzeige beim Client, und die korrekte Codierung des Links (bzw. des src-Attributs, wenn es um Bilder geht), wenn daraus wieder ein Request an den Server werden soll.

          Genau, für die Anzeige brauche ich utf8, für den Link ISO-8859-1.

          $name = utf8_encode($filename);

          echo "<a href='" . urlencode($name) . "'>$name</a>";

          
          >   
          
          Das mit urlencode muss ich noch ausprobieren.  
            
          Danke für den Tip.  
          
          
      3. hi,

        Vielleicht gibt es noch andere Möglichkeiten, aber dann müsste ich schon ein funktionierendes Beispiel sehen.

        Es kommt auf die Aufgabe an. Wenn es so ist, dass der eigentliche, im FS hinterlegte Dateiname auf der Anzeige im Browser gar keine Rolle spielt, würde ich serversitig einen Layer einschieben, der zwischen dem Dateinamen und dem im Browser angezeigten Namen eindeutig vermittelt; im einfachsten Fall bekämen die Dateien beispielsweise nur Nummern für die Ausgabe im Browser.

        Hotti