Christian: Encoding des Perl-Codes

Hallo,

wie kann man das Encoding von Perl-Skripten angeben?

Meine (CGI-)Skripte schreibe ich zwar in latin1, die Ausgabe ist aber meistens UTF-8, was ich natürlich auch im HTTP-Header, der xml-Deklaration und im HTML-Head angebe. Nun würde ich der Vollständigkeit halber gerne noch dem Interpreter sagen, dass mein Skript in latin1 geschrieben ist, damit es auch da keine Missverständnisse geben kann.

Nun habe ich gelesen, dass "use encoding ..." dafür nicht das richtige sein soll. Warum habe ich nicht ganz verstanden. Auch wundere ich mich, dass das Encoding nirgends angegeben wird. Dabei ist es doch immer wichtig zu wissen, welches Encoding die Daten haben. Oder nicht?

Viele Grüße
Christian

  1. Hallo,

    [..] Nun würde ich der Vollständigkeit halber gerne noch dem Interpreter sagen, dass mein Skript in latin1 geschrieben ist, damit es auch da keine Missverständnisse geben kann.

    Wenn das Script ausführbar ist, das Dateiformat, die shebang und der Syntax stimmt, gibt es keine Missverständnisse.

    Viele Grüße,
    Horst Haselhuhn

    1. Hallo,

      Wenn das Script ausführbar ist, das Dateiformat, die shebang und der Syntax stimmt, gibt es keine Missverständnisse.

      sorry, da komm ich nicht mit. Ich kann soweit zustimmen, dass alles kein Problem ist, wie ich nur ASCII-Zeichen verwende, also nur 7 bit, was offensichtlich für alles ausreicht, solange ich keine Strings verwende.

      Was aber, wenn ich in meinen Strings Umlaute nicht mit ä codiere, sondern einfach "ä" schreibe? Warum kann der Code nicht in iso-8859-2 geschrieben sein?

      Wenn ich meinen Code in UTF-8 schreibe, sage ich das Perl ja auch, indem ich "use utf8;" schreibe. Warum nicht das gleiche für latin1?

      Viele Grüße
      Christian

      1. Wenn ich meinen Code in UTF-8 schreibe, sage ich das Perl ja auch, indem ich "use utf8;" schreibe. Warum nicht das gleiche für latin1?

        Ich glaube, weil es für den Perl Interpreter keine Rolle spielt, ob deine komische Variable nun $hähö oder $hçhè heisst, solange die bytes identisch sind.
        Perl muss lediglich zwischen 8Bit und Unicode Byte-Ordnung unterscheiden können.

        mfg Beat

        --
        Woran ich arbeite:
        X-Torah
        ><o(((°>       ><o(((°>
           <°)))o><                      ><o(((°>o
        1. deine komische Variable nun $hähö oder $hçhè heisst, solange die bytes identisch sind.

          Oha, hier gibt es wohl ein Missverständnis ;-) Dann mach ich es jetzt mal ausführlicher. Ich meinte, wenn ich einen String habe und diesen dann ausgebe:

            
          use Encode;  
          binmode(STDOUT, ':utf8');  
          my $s = "schönes Wetter heute";  
          print $s;  
          
          

          Meine HTML-Seite ist in UTF-8 kodiert, mein CGI-Skript in latin1. Deshalb wird das "ö", bzw. das Byte \xF6, korrekt nach UTF-8 konvertiert. Wäre mein Skript aber iso-8859-4 oder so kodiert, hätte mein "ö" vielleicht einen anderen Oktetwert und dies müsste Perl wissen um es korrekt nach UTF-8 zu konvertieren.

          Genauso, wenn mein CGI-Skript in UTF-8 kodiert ist; dann belegt mein Zeichen "ö" zwei Bytes und ich schreibe "use utf8;" und schon klapppts wieder.

          Wenn ich "use utf8;" schreibe und mein Quelltext ist latin1 kodiert, dann beschwert sich Perl bei dem "ö" als "not well formed character".

          Perl muss eben wissen, in welchem Encoding mein Code geschrieben ist, damits bei Strings keine Probleme gibt.

          Hoffe meine Frage ist nun deutlicher geworden ;) Wenn nicht, einfach nochmal fragen.

          Viele Grüße
          Christian

          1. hi,

            binmode(STDOUT, ':utf8');
            my $s = "schönes Wetter heute";
            print $s;

            Deine print(); - Ausgaben sind dem Perl-Interpreter totalegal. Zumindest das Literal, was Du quotest und was auf <STDOUT> soll.

            Mit der Zeichenkodierung des Scripts hat das überhauptnichts zu tun.

            Hotte

            1. Hi,

              Deine print(); - Ausgaben sind dem Perl-Interpreter totalegal. Zumindest das Literal, was Du quotest und was auf <STDOUT> soll.

              Aber wenn ich nun Strings mit print $s; ausgebe, dann muss Perl doch wissen, ob mein $s nun UTF-8- oder iso-8859-1- oder sonstwie kodiert ist.

              Mit dem binmode fordere ich explizit UTF-8-Ausgabe, aber ist die Bytefolge \xC3\xB6 schon ein UTF8-kodiertes Zeichen oder sind das zwei Zeichen in iso-8859-1-Kodierung?

              Woher weiß Perl also, in welchem Encoding meine Literale kodiert sind?

              Viele Grüße
              Christian

              1. Aber wenn ich nun Strings mit print $s; ausgebe, dann muss Perl doch wissen, ob mein $s nun UTF-8- oder iso-8859-1- oder sonstwie kodiert ist.

                Nein, Perl verwendet intern Unicode, dem Interpreter ist es also ziemlich egal, was da kommt. Was Du wahrscheinlich suchst, ist die Frage nach dem charset für die Ausgabe, und die musst Du festlegen. Liegen die Daten in ISO-8859-4 vor, so teile dies STDOUT mit. Dafür gibt's das open-Pragma.

                Woher weiß Perl also, in welchem Encoding meine Literale kodiert sind?

                Das allerdings ist die Gretchenfrage, wie Du mit Perl ermittelst, welche Codierung vorliegt. Im besten Fall weißt Du es als Scriptautor selber, ansonsten solltest Du Eingaben von außen in eine einheitliche Codierung transformieren, siehe z.B. The 5-minute-tut.

                Siechfred

                --
                Obacht, hinter jedem noch so kleinen Busch könnte ein Indianer sitzen!
                1. Hallo zusammen :)

                  Danke für eure Antworten. Ich hab eben bemerkt, dass ich eine Ungenauigkeit in meinem vorherigen Posting hatte, deshalb kam wohl nicht die eigentliche Frage an.

                  Also nochmal: Ich möchte Perl mitteilen, in welchem Encoding meine Literale, bzw. meine hart kodierten Strings, innerhalb des Quelltextes vorliegen.

                  Das allerdings ist die Gretchenfrage, wie Du mit Perl ermittelst, welche Codierung vorliegt. Im besten Fall weißt Du es als Scriptautor selber,

                  Ich möchte die Kodierung ja nicht mit Perl ermitteln, sondern ich _kenne_ die Kodierung und diese Kodierung möchte ich am besten fest in der Datei stehen haben, sodass sie nicht verloren gehen kann.

                  Mir ist nun ein besseres Beispiel eingefallen. Sei da nun ein Programmierer, der seinen Code in iso-8859-15 schreibt und dann auch mal das Euro-Zeichen in einem Literal verwendet. Dann gibt er sein Skript einem anderen Programmierer und der denkt es ist iso-8859-1. Dann kommt eben an mancher Stelle kein Euro-Zeichen an.
                  Oder genauer: Falls die Ausgabe z.B. nach UTF-8 konvertiert wird, muss Perl doch wissen, dass in diesem Skript iso-15 gemeint ist, und deshalb das Byte \xA4 (Euro-Zeichen) in einen anderen Codepoint konvertiert werden muss, als wenn iso-1 verwendet würde.

                  Hoffe, das wird jetzt klarer, sonst gebe ich bald auf :)

                  ist die Frage nach dem charset für die Ausgabe, und die musst Du festlegen. Liegen die Daten in ISO-8859-4 vor, so teile dies STDOUT mit. Dafür gibt's das open-Pragma.

                  Das open-Pragma war mir bisher unbekannt, ich habe immer binmode() verwendet, um ein Encoding für einen Stream festzulegen. Das hat auch immer funktioniert. Ich sehe auch noch keine Vor- oder Nachteile, sondern nur eine weitere Möglichkeit, das zu bewerkstelligen. Kannst du da vielleicht noch was zu sagen? Danke.

                  Viele Grüße
                  Christian

                  1. Danke für eure Antworten. Ich hab eben bemerkt, dass ich eine Ungenauigkeit in meinem vorherigen Posting hatte, deshalb kam wohl nicht die eigentliche Frage an.

                    Doch, ich denke schon.

                    Also nochmal: Ich möchte Perl mitteilen, in welchem Encoding meine Literale, bzw. meine hart kodierten Strings, innerhalb des Quelltextes vorliegen.

                    Nein, diese Info benötigt Perl selber nicht, siehe Perl's Unicode Model.

                    Ich möchte die Kodierung ja nicht mit Perl ermitteln, sondern ich _kenne_ die Kodierung und diese Kodierung möchte ich am besten fest in der Datei stehen haben, sodass sie nicht verloren gehen kann.

                    Sie geht nicht verloren. Wenn es Dir hilft, schreib am Anfang des Scriptes einen Kommentar als Meta-Information.

                    Sei da nun ein Programmierer, der seinen Code in iso-8859-15 schreibt und dann auch mal das Euro-Zeichen in einem Literal verwendet. Dann gibt er sein Skript einem anderen Programmierer und der denkt es ist iso-8859-1.

                    Das ist zunächst irrelevant. Es gibt einen einzigen Fall, den ich mir gerade vorstellen kann:

                    use utf8;  
                    my $€ = 'Euro';
                    

                    Andersrum:

                    my $Euro = '€';

                    brauchst Du Perl nirgendwo mitzuteilen, dass es für die Verarbeitung des Strings bitteschön ISO-8859-15 verwenden soll. Erst wenn Du den String *ausgeben* willst, solltest Du explizit festlegen, in welcher Codierung er vorliegt:

                    use open OUT => ':encoding(iso-8859-15)';  
                    print $Euro;
                    

                    Dann kommt eben an mancher Stelle kein Euro-Zeichen an.

                    Siehste, auf das "Ankommen" kommt's an ;)

                    Perl verwendet bei Ausgaben automatisch die interne Codierung (Link dazu s.o.). Liegen die auszugebenden Daten aber in einer anderen Codierung vor, muss man den Kanal, den man benutzen will (STDIN, STDOUT) auf diese Codierung "einstellen".

                    Oder genauer: Falls die Ausgabe z.B. nach UTF-8 konvertiert wird, muss Perl doch wissen, dass in diesem Skript iso-15 gemeint ist, und deshalb das Byte \xA4 (Euro-Zeichen) in einen anderen Codepoint konvertiert werden muss, als wenn iso-1 verwendet würde.

                    Wie gesagt, intern läuft das automagisch, extern musst Du es explizit angeben, wenn es von der nativen Codierung des Scriptes abweicht.

                    Das open-Pragma war mir bisher unbekannt, ich habe immer binmode() verwendet, um ein Encoding für einen Stream festzulegen. Das hat auch immer funktioniert. Ich sehe auch noch keine Vor- oder Nachteile, sondern nur eine weitere Möglichkeit, das zu bewerkstelligen. Kannst du da vielleicht noch was zu sagen? Danke.

                    Ich finde es halt besser zu handeln.

                    Siechfred

                    --
                    Obacht, hinter jedem noch so kleinen Busch könnte ein Indianer sitzen!
                    1. Danke für die Antworten! Ich werde jetzt nochmal ein bisschen für mich drüber nachdenken und hoffentlich die richtigen Schlüsse ziehen ;)

                      Viele Grüße
                      Christian

  2. wie kann man das Encoding von Perl-Skripten angeben?

    Meine (CGI-)Skripte schreibe ich zwar in latin1, die Ausgabe ist aber meistens UTF-8, was ich natürlich auch im HTTP-Header, der xml-Deklaration und im HTML-Head angebe. Nun würde ich der Vollständigkeit halber gerne noch dem Interpreter sagen, dass mein Skript in latin1 geschrieben ist, damit es auch da keine Missverständnisse geben kann.

    Da gibt es kein Missverständnis, so lange du es nicht erzeugst.
    Perl weiss sehr wohl die Sprache des Scripts, die zur Runtime schon längst in etwas anderes verarbeitet ist, zu unterscheiden von Inhalt, der in Variablen geschrieben wird.

    mfg Beat

    --
    Woran ich arbeite:
    X-Torah
    ><o(((°>     ><o(((°>
       <°)))o><                      ><o(((°>o