sepp: Umlaute ersetzen

Hallo,
ich will mit PHP aus Dateinamen die Umlaute werfen.

1. Veruch:
  $umlaute = array("ä", "Ä", "ö", "Ö", "ü", "Ü", 'ß');
  $vokale = array("ae", "Ae", "oe", "Oe", "ue", "Ue", 'ss');

$newfilename = str_replace($umlaute, $vokale, $filename);

Ergebnis: Aus "Nürnberg" wird "Nürnberg"
Internet angeworfen. Aha, UTF-8 Problem.

2. Versuch:
  $newfilename = utf8_decode($file);
  $newfilename = str_replace($umlaute, $vokale, $newfilename);

Ergebnis: Aus "Nürnberg" wird "Nu?rnberg".

Was ist hier falsch?

  1. Hi,

    $umlaute = array("ä", "Ä", "ö", "Ö", "ü", "Ü", 'ß');
      $vokale = array("ae", "Ae", "oe", "Oe", "ue", "Ue", 'ss');

    $newfilename = str_replace($umlaute, $vokale, $filename);

    Ergebnis: Aus "Nürnberg" wird "Nürnberg"

    Bei mir nicht.

    Internet angeworfen. Aha, UTF-8 Problem.

    UTF-8 verwendet, kein Problem.

    1. Versuch:
        $newfilename = utf8_decode($file);
        $newfilename = str_replace($umlaute, $vokale, $newfilename);

    Ergebnis: Aus "Nürnberg" wird "Nu?rnberg".

    Es wurde wieder nichts ersetzt - aber aus dem UTF-8-ü hast du jetzt durch die „Dekodierung” ein Fragezeichen gemacht.

    MfG ChrisB

    --
    “Whoever best describes the problem is the person most likely to solve the problem.” [Dan Roam]
    1. N'abend

      UTF-8 verwendet, kein Problem.

      Komisch. Habe jetzt Folgendes probiert:

      Dateiname unverändert auf der Seite ausgeben lassen ("Neues aus Nürnberg.doc").
      Dateiname kopiert & in eine Testvariable reingeschrieben:

      $test="Neues aus Nürnberg.doc";

      Denselben Code durchnudeln lassen und ..... es funktioniert wie gewünscht! Wie kann das sein?

      Die Dateiname-Variable kommt so zu Ihrem Inhalt:

      $buzz = @opendir($dir);  
      $file = readdir($buzz);
      

      Der Rückgabewert von readdir ist doch ein String. Wo ist also hier der Unterschied?

      Vielen Dank
      sepp

      1. Hi,

        Die Dateiname-Variable kommt so zu Ihrem Inhalt:

        $buzz = @opendir($dir);

        $file = readdir($buzz);

        
        >   
        > Der [Rückgabewert von readdir](http://php.net/manual/de/function.readdir.php) ist doch ein String. Wo ist also hier der Unterschied?  
          
        Das Dateisystem muss nicht unbedingt die Kodierung verwenden, die du scriptintern verwendest.  
          
        MfG ChrisB  
          
        
        -- 
        “Whoever best describes the problem is the person most likely to solve the problem.” [Dan Roam]
        
        1. Das Dateisystem muss nicht unbedingt die Kodierung verwenden, die du scriptintern verwendest.

          Hm, das hilft mir jetzt nur bedingt. Wie überprüfe/änder/handle ich das denn dann?

          Danke & Gruß
          sepp

          1. Moin!

            Das Dateisystem muss nicht unbedingt die Kodierung verwenden, die du scriptintern verwendest.

            Hm, das hilft mir jetzt nur bedingt. Wie überprüfe/änder/handle ich das denn dann?

            So wie dein Fehlerbild aussieht: Das Dateisystem gibt ISO-8859-1 zurück, und dein Skript ist in UTF-8.

            Dann zerstörst du mit utf8_decode() den Umlaut im Dateinamen (weil der in ISO ist), und kriegst stattdessen das Fragezeichen.

            Mit utf8_encode() hingegen würde es vermutlich gehen. AAAAAABER: Warum würde es das? Woher weißt du das Encoding des Dateisystems? Kann garantiert sein, dass dein Skript immer auf Systemen läuft, die als Dateinamensystem ISO-8859-1 benutzen? Wohl kaum. Auf welchem Betriebssystem läuft dein Skript derzeit? Und ist das schon direkt der Server, auf dem die Sache auch später laufen soll?

            - Sven Rautenberg

            1. Guten Morgen (hoffentlich :-)

              So wie dein Fehlerbild aussieht: Das Dateisystem gibt ISO-8859-1 zurück, und dein Skript ist in UTF-8.

              Dann zerstörst du mit utf8_decode() den Umlaut im Dateinamen (weil der in ISO ist), und kriegst stattdessen das Fragezeichen.

              Mit utf8_encode() hingegen würde es vermutlich gehen.

              Damit bekomme ich das hier zurück.

              AAAAAABER: Warum würde es das? Woher weißt du das Encoding des Dateisystems? Kann garantiert sein, dass dein Skript immer auf Systemen läuft, die als Dateinamensystem ISO-8859-1 benutzen? Wohl kaum. Auf welchem Betriebssystem läuft dein Skript derzeit? Und ist das schon direkt der Server, auf dem die Sache auch später laufen soll?

              Ich teste gerade lokal mit MAMP unter Mac OS X.
              "Apache/2.0.59 (Unix) PHP/5.2.6 DAV/2 Server at localhost Port 80".

              Später soll das script online laufen, vermutl. auf einem eigenen V-Server (Unix).

              Sorry, ich hab echt null Plan. Ich will doch einfach nur die Umlaute loswerden...... :-)

              Bin für jeden weiteren Tipp dankbar!
              Gruß, sepp

              1. Dabanyoa!

                Mit utf8_encode() hingegen würde es vermutlich gehen.

                Damit bekomme ich das hier zurück.

                Oh, das ist spannend. Das bedeutet, daß Dein String nicht nur in UTF-8, sondern auch noch in der Normalisierungsform NFD vorliegt. Du hast also gar kein ü darin, sondern die Folge
                U+0075 LATIN SMALL LETTER U
                U+0308 COMBINING DIAERESIS

                Sorry, ich hab echt null Plan. Ich will doch einfach nur die Umlaute loswerden...... :-)

                Da ist schon der Ansatz nicht ganz unproblematisch. Was machst Du mit "Ingredentiën.doc", "Stanisławs Article.doc", "Москва.doc", …?

                Viele Grüße vom Længlich

                --
                Mein aktueller Gruß ist:
                Sara (gesprochen im Tschad)
                1. Hi!

                  Damit bekomme ich das hier zurück.
                  Oh, das ist spannend. Das bedeutet, daß Dein String nicht nur in UTF-8, sondern auch noch in der Normalisierungsform NFD vorliegt. Du hast also gar kein ü darin, sondern die Folge
                  U+0075 LATIN SMALL LETTER U
                  U+0308 COMBINING DIAERESIS

                  Typisch MAC OS. Kein anderes mir bekanntes Betriebssystem macht das so.

                  Sorry, ich hab echt null Plan. Ich will doch einfach nur die Umlaute loswerden...... :-)

                  Da kann man nur diese Bytefolgen als Suchkriterium verwenden. Ich würde aber vorher mal probieren, wie die Umlaute, wenn sie aus Dateinamen kopiert werden, im Script landen. Also kopieren, einfügen und mit einem Hexeditor anschauen, ob 75 CC 88 drinsteht. (CC 88 ist UTF-8 für U+0308.)

                  Da ist schon der Ansatz nicht ganz unproblematisch. Was machst Du mit "Ingredentiën.doc", "Stanisławs Article.doc", "Москва.doc", …?

                  Hat er ja bei seiner Lösung von vorn herein nicht berücksichtigt. Wird vielleicht nicht vorkommen.

                  Lo!

                  1. Hallo nochmal,
                    vielen Dank Euch allen für die Tipps, aber ich steig hier aus - ich komm nicht mehr mit.

                    Hab das Problem jetzt anders gelöst: Batch rename :)

                    Vielen Dank trotzdem für eure Mühe!
                    sepp

                    1. Hi!

                      vielen Dank Euch allen für die Tipps, aber ich steig hier aus - ich komm nicht mehr mit.

                      MAC OS X hat sich für sein Dateisystem dazu entschieden, keine kombinierten Zeichen zu verwenden (ü) sondern nicht kombinierte (u + ̈). Es gibt nämlich mehr Kombinationsmöglichkeiten von lateinischen Buchstaben und diakritischen "Schnörkeln" als eigenständige Zeichen dafür in Unicode vorgesehen sind. Und damit man Unicode nicht mit all diesen Möglichkeiten vollpflastern muss, hat man diesen Combining Diacritical Marks einen eigenen Bereich gegeben und definiert: Wenn sie einem anderen Zeichen folgen, werden beide Zeichen zu einem verbunden. (Ist jetzt vielleicht nicht 100% korrekt formuliert, aber die grobe Richtung dürfte klar sein.)

                      Wenn du nun in deinem Texeditor ein ü eingibst, und der speichert es als kombiniertes Zeichen, dann kann der Vergleich mit "u gefolgt von ̈" keine Übereinstimmung ergeben. Du musst also sowohl nach ü (für andere Betriebs-/Dateisysteme) suchen, also auch nach u + ̈ suchen und das ersetzen.

                      Lo!

                      1. Ci yi bak!

                        Es gibt nämlich mehr Kombinationsmöglichkeiten von lateinischen Buchstaben und diakritischen "Schnörkeln" als eigenständige Zeichen dafür in Unicode vorgesehen sind. Und damit man Unicode nicht mit all diesen Möglichkeiten vollpflastern muss, hat man diesen Combining Diacritical Marks einen eigenen Bereich gegeben und definiert: Wenn sie einem anderen Zeichen folgen, werden beide Zeichen zu einem verbunden. (Ist jetzt vielleicht nicht 100% korrekt formuliert, aber die grobe Richtung dürfte klar sein.)

                        Stimmt schon, gilt aber nicht nur für lateinische Buchstaben. Besonders süd- und südostasiatische Schriften verwenden sehr viele Diakritika. Devanagari z.B. würde mehrere hundert Codepoints verschlingen, wenn man alle möglichen Kombinationen und Ligaturen aufgenommen hätte. So sind nur 112 definiert.

                        Wenn du nun in deinem Texeditor ein ü eingibst, und der speichert es als kombiniertes Zeichen, dann kann der Vergleich mit "u gefolgt von ̈" keine Übereinstimmung ergeben. Du musst also sowohl nach ü (für andere Betriebs-/Dateisysteme) suchen, also auch nach u + ̈ suchen und das ersetzen.

                        Ja, oder den String vorher in eine bestimmte Normalisierungsform bringen. Welche, ist im Prinzip egal.

                        Viele Grüße vom Længlich

                        --
                        Mein aktueller Gruß ist:
                        Dinka (gesprochen im Sudan)
                        1. Hi!

                          Du musst also sowohl nach ü (für andere Betriebs-/Dateisysteme) suchen, also auch nach u + ̈ suchen und das ersetzen.
                          Ja, oder den String vorher in eine bestimmte Normalisierungsform bringen. Welche, ist im Prinzip egal.

                          Prinzipiell keine schlechte Idee, wenn man ein passendes Werkzeug dafür hat. Das liefert PHP jedoch nicht mit, und das Suchen danach ist sicher mindestens genauso aufwendig wie das händische Berücksichtigen der 6 potentiellen Kandidaten.

                          Lo!

                          1. Nkuba!

                            Du musst also sowohl nach ü (für andere Betriebs-/Dateisysteme) suchen, also auch nach u + ̈ suchen und das ersetzen.
                            Ja, oder den String vorher in eine bestimmte Normalisierungsform bringen. Welche, ist im Prinzip egal.

                            Prinzipiell keine schlechte Idee, wenn man ein passendes Werkzeug dafür hat. Das liefert PHP jedoch nicht mit, und das Suchen danach ist sicher mindestens genauso aufwendig wie das händische Berücksichtigen der 6 potentiellen Kandidaten.

                            In diesem speziellen Anwendungsfall (keine passende Funktion vorhanden und nur sehr wenige mögliche Kandidaten) hast Du recht, für andere Sprachen kann das aber gruselig werden.
                            Fürs Archiv ein Beispiel aus dem Việtnamesischen:

                            U+1EC7 ệ LATIN SMALL LETTER E WITH CIRCUMFLEX AND DOT BELOW

                            U+1EB9 ẹ LATIN SMALL LETTER E WITH DOT BELOW
                            U+0302  ̂ COMBINING CIRCUMFLEX ACCENT

                            U+0065 e LATIN SMALL LETTER E
                            U+0323  ̣ COMBINING DOT BELOW
                            U+0302  ̂ COMBINING CIRCUMFLEX ACCENT

                            U+0065 e LATIN SMALL LETTER E
                            U+0302  ̂ COMBINING CIRCUMFLEX ACCENT
                            U+0323  ̣ COMBINING DOT BELOW

                            U+00EA ê LATIN SMALL LETTER E WITH CIRCUMFLEX
                            U+0323  ̣ COMBINING DOT BELOW

                            Daß die Reihenfolge der Diakritika egal ist, ist aber auch nicht allgemeingültig – z.B. bei ể ist das nicht so.

                            Viele Grüße vom Længlich

                            --
                            Mein aktueller Gruß ist:
                            Ejagham (gesprochen in Kamerun und Nigeria)
  2. h1,

    $umlaute = array("ä", "Ä", "ö", "Ö", "ü", "Ü", 'ß');

    Hast Du das getippt? Dann weißt Du auch, in welcher Codierung Du das Getippte abgespeichert hast ;-)

    Hotti

    1. Hast Du das getippt? Dann weißt Du auch, in welcher Codierung Du das Getippte abgespeichert hast ;-)

      Jo, ich tippte im Dreamweaver und Encoding steht hier auf "Unicode 5.1 UTF-8).
      Sollte eigentl. passen, oder?

      danke & gruß
      sepp