UTF-8-codierte Umlaute via print und warn ausgeben

UTF-8-codierte Umlaute via print und warn ausgeben

am 07.08.2007 21:58:31 von Johannes

Hallo allerseits,

beim Versuch, sowohl via print als auch via warn Umlaute auszugeben, bin
ich auf folgendes Verhalten bei meinem Ubuntu Linux 6.10 (mit Perl 5.8.8)
gestossen, das ich nicht ganz verstehe:

: johannes@ford:~/bin$ cat ./foo.pl # Terminal auf UTF-8 gestellt
: #!/usr/bin/perl
: use strict;
: use warnings;
: # use utf8;
: my $s = "öäüÖÄÜß\n";
: print $s;
: warn $s;
:
: johannes@ford:~/bin$ ./foo.pl
: öäüÖÄÜß
: öäüÖÄÜß
: johannes@ford:~/bin$ ./foo.pl # use utf8 wieder einkommentiert
: ��
: öäüÖÄÜß
: johannes@ford:~/bin$ ./foo.pl # Terminal auf ISO-8859-15 gestellt
: öäüÖÄÜß
: öÀÌÖÄÜß
: johannes@ford:~/bin$ ./foo.pl # ISO-8859-15 Terminal, use utf8 auskommentiert
: öÀÌÖÄÜß
: öÀÌÖÄÜß

Mich wundert daran,
1. dass ich ohne #use utf8 bereits eine vernuenftige Ausgabe bekomme.
2. dass mit #use utf8, je nach verwendeter Terminal-Einstellung entweder
die print- oder die warn-Ausgabe kaputt ist.

Fuer mich sieht das so aus, als wuerde ohne 'use utf8' der String
unveraendert aufs Terminal gekippt, waehrend mit 'use utf8' fuer die
Standardausgabe irgendwelche Magie (Umwandlung in ISO-8859-15-codierte
Zeichen) veranstaltet wird, die ich gern verstehen und beeinflussen
wuerde. STDERR unterliegt diesem Umwandlungszauber scheinbar nicht.

Unter Windows/Cygwin im Cygwin-Terminal mit Cygwins Perl (5.8.7):

: ~/Perl$ cat ./foo.pl # im "Cygwin-Terminal"
: #!/usr/bin/perl
: use strict;
: use warnings;
: # use utf8;
: my $s = "Ã-Ã"ÃoöäüÃY\n";
: print $s;
: warn $s;
: ~/Perl$ ./foo.pl
: Ã-Ã"ÃoöäüÃY
: Ã-Ã"ÃoöäüÃY
: ~/Perl$ ./foo.pl # mit einkommentiertem use utf8
: ÖÄÜöäüß
: Ã-Ã"ÃoöäüÃY
: ~/Perl$ /cygdrive/c/WINNT/system32/chcp.com 1252
: Aktive Codepage: 1252.
: ~/Perl$ ./foo.pl
: ÖÄÜöäüß
: ÖÄÜöäüß
: ~/Perl$ ./foo.pl # wieder mit auskommentierem use utf8
: ÖÄÜöäüß
: ÖÄÜöäüß
: ~/Perl$

Im UTF-8-Xterm funktioniert die Umlautausgabe mit print und warn,
wenn 'use utf8' auskommentiert ist. Wenn es nicht auskommentiert ist,
funktioniert nur warn. Die Ausgabe des Xterms laesst sich leider nur
stark verlustbehaftet in den Editor uebernehmen, deswegen spare ich
sie mir an dieser Stelle.

Mit ActivePerl 5.8.8 aus cmd.exe aufgerufen erhalte ich:

: C:\home\loewjoha\Perl>type foo.pl
: #!/usr/bin/perl
: use strict;
: use warnings;
: # use utf8;
: my $s = "├û├ä├£├Â├ñ├╝├ƒ\n";
: print $s;
: warn $s;
:
: C:\home\loewjoha\Perl>perl foo.pl
: ├û├ä├£├Â├ñ├╝├ƒ
: ├û├ä├£├Â├ñ├╝├ƒ
:
: C:\home\loewjoha\Perl>perl foo.pl ! mit use utf8
: Í─▄÷õ³▀
: ├û├ä├£├Â├ñ├╝├ƒ
:
: C:\home\loewjoha\Perl>chcp 1252
: Aktive Codepage: 1252.
:
: C:\home\loewjoha\Perl>perl foo.pl
: ÖÄÜöäüß
: ÖÄÜöäüß
:
: C:\home\loewjoha\Perl>perl foo.pl ! ohne use utf8
: ÖÄÜöäüß
: ÖÄÜöäüß


Die Manpage zu utf8 verstehe ich so, dass ich mit dem Pragma erklaere,
dass mein Script UTF-8-codiert ist, und dass, wenn UTF-8 irgendwann das
"standard source format" wird, es (das Pragma) zumindest keinen Schaden
anrichtet. Mir scheint, der zweite foo.pl-Aufruf unter Linux (und im
UTF-8-Xterm unter Cygwin) widerspricht dieser Aussage.

Eigentlich bin ich auf der Suche nach einer Moeglichkeit, ein Script
(am liebsten UTF-8-codiert) so zu schreiben, dass es unter Linux, unter
Cygwin Perl (im xterm und im "gewoehnlichen" Cygwin-Terminal) und auch
unter ActivePerl (Windows, cmd.exe) sowohl via print als auch via warn
umlauthaltige Strings ausgeben kann.

Bei Windows/ActivePerl/cmd.exe habe ich, wie man sieht, noch gar keine
Loesung fuer das Umlautausgabeproblem gefunden. Hier waere mir auch
schon mit einer Windows-only-Loesung geholfen. Etwas portables waere
mir natuerlich lieber.

Ich freue mich ueber jede Erklaerung, die Licht in die Dunkle Kunst der
Umlautausgabe bringt.

Herzliche Gruesse

Johannes

Re: UTF-8-codierte Umlaute via print und warn ausgeben

am 08.08.2007 14:26:35 von hjp-usenet2

On 2007-08-07 19:58, Johannes v. Löwis wrote:
>
> Hallo allerseits,
>
> beim Versuch, sowohl via print als auch via warn Umlaute auszugeben, bin
> ich auf folgendes Verhalten bei meinem Ubuntu Linux 6.10 (mit Perl 5.8.8)
> gestossen, das ich nicht ganz verstehe:
>
>: johannes@ford:~/bin$ cat ./foo.pl # Terminal auf UTF-8 gestellt
>: #!/usr/bin/perl
>: use strict;
>: use warnings;
>: # use utf8;
>: my $s = "öäüÖÄÜß\n";
>: print $s;
>: warn $s;
>:
>: johannes@ford:~/bin$ ./foo.pl
>: öäüÖÄÜß
>: öäüÖÄÜß
>: johannes@ford:~/bin$ ./foo.pl # use utf8 wieder einkommentiert
>: ��
>: öäüÖÄÜß
>: johannes@ford:~/bin$ ./foo.pl # Terminal auf ISO-8859-15 gestellt
>: öäüÖÄÜß
>: öÀÌÖÄÜß
>: johannes@ford:~/bin$ ./foo.pl # ISO-8859-15 Terminal, use utf8 auskommentiert
>: öÀÌÖÄÜß
>: öÀÌÖÄÜß
>
> Mich wundert daran,
> 1. dass ich ohne #use utf8 bereits eine vernuenftige Ausgabe bekomme.

Da heben sich zwei Fehler gegenseitig auf.

1. Fehler: Du hast ein Script in UTF-8 geschrieben, sagst aber dem
Interpreter nicht, dass es UTF-8 ist. Er nimmt daher an, dass es
irgendein nicht näher spezifizierter 8-Bit-Zeichensatz ist. Dein String
$s besteht daher aus 15 Zeichen.

2. Fehler: Du sagst Deinem Script nicht, dass es UTF-8 für STDOUT
verwenden soll. Daher wird jedes der 15 Zeichen als ein Byte ausgegeben.

Das Terminal interpretiert dann die 15 Bytes als 8 UTF-8-Zeichen und
somit ist alles wieder paletti.

> 2. dass mit #use utf8, je nach verwendeter Terminal-Einstellung entweder
> die print- oder die warn-Ausgabe kaputt ist.
>
> Fuer mich sieht das so aus, als wuerde ohne 'use utf8' der String
> unveraendert aufs Terminal gekippt, waehrend mit 'use utf8' fuer die
> Standardausgabe irgendwelche Magie (Umwandlung in ISO-8859-15-codierte
> Zeichen) veranstaltet wird,

Nein, die "Magie" fehlt eben hier, darum werden die Zeichen als Bytes
ausgegeben, und nicht in UTF-8 umgewandelt. Abhilfe schafft ein

binmode STDOUT, ":utf8";

nahe dem Anfang des Scripts oder alternativ die Option -CO in der
Shebang-Zeile.

warn scheint eine entsprechende "Magie" zu haben.

> Eigentlich bin ich auf der Suche nach einer Moeglichkeit, ein Script
> (am liebsten UTF-8-codiert) so zu schreiben, dass es unter Linux, unter
> Cygwin Perl (im xterm und im "gewoehnlichen" Cygwin-Terminal) und auch
> unter ActivePerl (Windows, cmd.exe) sowohl via print als auch via warn
> umlauthaltige Strings ausgeben kann.

Dazu musst Du feststellen, welches Encoding das verwendete Terminal
verwendet. Diese Information sollte man aus der Locale bekommen:

use I18N::Langinfo qw(langinfo CODESET)
$charset = langinfo(CODESET)

binmode STDIN, ":encoding($charset)";
binmode STDOUT, ":encoding($charset)";

Wenn I18N::Langinfo in ActivePerl existiert, sollte $charset für von
cmd.exe gestartete Programme wohk 'cp850' oder ähnlich sein.

hp


--
_ | Peter J. Holzer | I know I'd be respectful of a pirate
|_|_) | Sysadmin WSR | with an emu on his shoulder.
| | | hjp@hjp.at |
__/ | http://www.hjp.at/ | -- Sam in "Freefall"

Re: UTF-8-codierte Umlaute via print und warn ausgeben

am 08.08.2007 20:33:06 von Slaven Rezic

"Peter J. Holzer" writes:

> On 2007-08-07 19:58, Johannes v. Löwis wrote:
[...]
>
> > Eigentlich bin ich auf der Suche nach einer Moeglichkeit, ein Script
> > (am liebsten UTF-8-codiert) so zu schreiben, dass es unter Linux, unter
> > Cygwin Perl (im xterm und im "gewoehnlichen" Cygwin-Terminal) und auch
> > unter ActivePerl (Windows, cmd.exe) sowohl via print als auch via warn
> > umlauthaltige Strings ausgeben kann.
>
> Dazu musst Du feststellen, welches Encoding das verwendete Terminal
> verwendet. Diese Information sollte man aus der Locale bekommen:
>

Leider kann man sich auf diese Information nicht verlassen. Ich kann
in meinem xterm per Menü UTF-8 ein- und ausschalten --- die Locale
wird damit nicht geändert. Umgekehrt kann ich auch die LC_*- und
LANG-Environment-Variablen ändern, ohne dass dies in der
Terminaleinstellung reflektiert wird.

Gruß,
Slaven

--
Slaven Rezic - slaven rezic de

Dump a Tk canvas as an xfig file:
http://search.cpan.org/search?mode=module&query=Tk::CanvasFi g

Re: UTF-8-codierte Umlaute via print und warn ausgeben

am 09.08.2007 00:27:21 von hjp-usenet2

On 2007-08-08 18:33, Slaven Rezic wrote:
> "Peter J. Holzer" writes:
>
>> On 2007-08-07 19:58, Johannes v. Löwis wrote:
> [...]
>> Dazu musst Du feststellen, welches Encoding das verwendete Terminal
>> verwendet. Diese Information sollte man aus der Locale bekommen:
>>
>
> Leider kann man sich auf diese Information nicht verlassen. Ich kann
> in meinem xterm per Menü UTF-8 ein- und ausschalten --- die Locale
> wird damit nicht geändert. Umgekehrt kann ich auch die LC_*- und
> LANG-Environment-Variablen ändern, ohne dass dies in der
> Terminaleinstellung reflektiert wird.

Ja. Um Henry Spencer zu paraphrasieren: If you lie to the computer it
will get its revenge.

hp


--
_ | Peter J. Holzer | I know I'd be respectful of a pirate
|_|_) | Sysadmin WSR | with an emu on his shoulder.
| | | hjp@hjp.at |
__/ | http://www.hjp.at/ | -- Sam in "Freefall"

Re: UTF-8-codierte Umlaute via print und warn ausgeben

am 09.08.2007 21:27:00 von Slaven Rezic

"Peter J. Holzer" writes:

> On 2007-08-08 18:33, Slaven Rezic wrote:
> > "Peter J. Holzer" writes:
> >
> >> On 2007-08-07 19:58, Johannes v. Löwis wrote:
> > [...]
> >> Dazu musst Du feststellen, welches Encoding das verwendete Terminal
> >> verwendet. Diese Information sollte man aus der Locale bekommen:
> >>
> >
> > Leider kann man sich auf diese Information nicht verlassen. Ich kann
> > in meinem xterm per Menü UTF-8 ein- und ausschalten --- die Locale
> > wird damit nicht geändert. Umgekehrt kann ich auch die LC_*- und
> > LANG-Environment-Variablen ändern, ohne dass dies in der
> > Terminaleinstellung reflektiert wird.
>
> Ja. Um Henry Spencer zu paraphrasieren: If you lie to the computer it
> will get its revenge.

Das kann schnell versehentlich passieren, z.B. indem man sich per ssh
auf einen anderen Rechner einloggt. Typischerweise gehen die
Locale-Variablen dabei verloren.

--
Slaven Rezic - slaven rezic de

Start a WWW browser - OS independent:
http://user.cs.tu-berlin.de/~eserte/src/perl/WWWBrowser/

Re: UTF-8-codierte Umlaute via print und warn ausgeben

am 09.08.2007 22:38:43 von Johannes

Hallo Peter,

ich danke Dir fuer Deine Antwort, richtig verstanden habe ich die
Zusammenhaenge aber immer noch nicht...

Peter J. Holzer wrote:
> On 2007-08-07 19:58, Johannes v. Löwis wrote:
>> 2. dass mit #use utf8, je nach verwendeter Terminal-Einstellung entweder
>> die print- oder die warn-Ausgabe kaputt ist.
>>
>> Fuer mich sieht das so aus, als wuerde ohne 'use utf8' der String
>> unveraendert aufs Terminal gekippt, waehrend mit 'use utf8' fuer die
>> Standardausgabe irgendwelche Magie (Umwandlung in ISO-8859-15-codierte
>> Zeichen) veranstaltet wird,
>
> Nein, die "Magie" fehlt eben hier, darum werden die Zeichen als Bytes
> ausgegeben, und nicht in UTF-8 umgewandelt. Abhilfe schafft ein
>
> binmode STDOUT, ":utf8";
>
> nahe dem Anfang des Scripts oder alternativ die Option -CO in der
> Shebang-Zeile.
>
> warn scheint eine entsprechende "Magie" zu haben.

Auf Deine Hinweise hin habe ich etwas weiter herumprobiert (im
UTF-8-Terminal unter Linux):

: johannes@ford:~/bin$ cat ./foo.pl
: #!/usr/bin/perl
: use strict;
: use warnings;
: use utf8;
: use I18N::Langinfo qw(langinfo CODESET);
: my $charset = langinfo(CODESET);
: print "charset = $charset\n";
: binmode STDERR, ":encoding($charset)";
: binmode STDOUT, ":encoding($charset)";
: my $s = "öäüÖÄÜß\n";
: print $s;
: warn $s;
: print STDERR $s;
: die $s;
:
: johannes@ford:~/bin$ ./foo.pl
: charset = UTF-8
: öäüÖÄÜß
: öäüÖÄÜß
: öäüÖÄÜß
: öäüÖÄÜß
: johannes@ford:~/bin$ ./foo.pl # binmode STDERR auskommentiert
: charset = UTF-8
: öäüÖÄÜß
: öäüÖÄÜß
: ��
: öäüÖÄÜß
: johannes@ford:~/bin$ ./foo.pl # binmode STDOUT auskommentiert
: charset = UTF-8
: ��
: öäüÖÄÜß
: öäüÖÄÜß
: öäüÖÄÜß
: johannes@ford:~/bin$ ./foo.pl # binmode STDOUT,STDERR auskommentiert
: charset = UTF-8
: ��
: öäüÖÄÜß
: ��
: öäüÖÄÜß
: johannes@ford:~/bin$

Es sieht also so aus, als koennte ich durch geeignete binmode-Aufrufe
auf STDERR und STDOUT eine brauchbare UTF-8-Ausgabe erzielen, solange
ich diese via 'print' bewerkstellige. Fuer 'die' und 'warn', die laut
Dokumentation auf STDERR ausgeben, scheint der binmode von STDERR keine
Bedeutung zu haben. Das finde ich zumindest seltsam...

Die Unempfindlichkeit von 'die' und 'warn' gegenueber der
binmode-Einstellung von STDERR wird dann zum Problem, wenn ich aus einem
UTF-8-Script heraus, bei dem ich fuer STDERR und STDOUT jeweils als
binmode ":bytes" eingestellt habe, umlauthaltige Strings auf einem
ISO-8859-15 Terminal ausgebe.

Mit scheint, 'die' und 'warn' kippen den String einfach aufs Terminal
und scheren sich einen Dreck um Nicht-ASCII-Zeichen und -Codierungen.
'die' und 'warn' fehlt also die Magie.

>> Eigentlich bin ich auf der Suche nach einer Moeglichkeit, ein Script
>> (am liebsten UTF-8-codiert) so zu schreiben, dass es unter Linux, unter
>> Cygwin Perl (im xterm und im "gewoehnlichen" Cygwin-Terminal) und auch
>> unter ActivePerl (Windows, cmd.exe) sowohl via print als auch via warn
>> umlauthaltige Strings ausgeben kann.
>
> Dazu musst Du feststellen, welches Encoding das verwendete Terminal
> verwendet. Diese Information sollte man aus der Locale bekommen:
>
> use I18N::Langinfo qw(langinfo CODESET)
> $charset = langinfo(CODESET)
>
> binmode STDIN, ":encoding($charset)";
> binmode STDOUT, ":encoding($charset)";
>
> Wenn I18N::Langinfo in ActivePerl existiert, sollte $charset für von
> cmd.exe gestartete Programme wohk 'cp850' oder ähnlich sein.

I18N::Langinfo ist zumindest nicht im Default-Paketbestand von
ActivePerl. Ob das Modul fuer ActivePerl existiert, habe ich noch nicht
ueberprueft.

Unter Ubuntu Linux 6.10 (Perl 5.8.8) habe ich uebrigens folgendes
beobachtet:

: johannes@ford:~/bin$ cat bar.pl
: #!/usr/bin/perl
: binmode STDERR, ":encoding('cp850')";
: johannes@ford:~/bin$ ./bar.pl
: Segmentation fault (core dumped)

Was dieser Code bei ActivePerl macht, werde ich morgen ausprobieren.

Gruss
Johannes

Re: UTF-8-codierte Umlaute via print und warn ausgeben

am 09.08.2007 22:59:14 von Slaven Rezic

"Johannes v. Löwis" writes:

[...]
>
> Mit scheint, 'die' und 'warn' kippen den String einfach aufs Terminal
> und scheren sich einen Dreck um Nicht-ASCII-Zeichen und -Codierungen.
> 'die' und 'warn' fehlt also die Magie.
>

Dieses Beobachtung habe ich auch schon gemacht.

[...]
>
> Unter Ubuntu Linux 6.10 (Perl 5.8.8) habe ich uebrigens folgendes
> beobachtet:
>
> : johannes@ford:~/bin$ cat bar.pl
> : #!/usr/bin/perl
> : binmode STDERR, ":encoding('cp850')";
> : johannes@ford:~/bin$ ./bar.pl
> : Segmentation fault (core dumped)
>
> Was dieser Code bei ActivePerl macht, werde ich morgen ausprobieren.
>

Das Problem (eine Endlosschleife) tritt auch bei FreeBSD 6.2 + Perl
5.8.8 auf. Bei bleedperl tritt es nicht auf. Vielleicht ist es der
folgende Patch, der das Problem behoben hat?

[ 29743] By: rgs on 2007/01/10 10:54:27
Log: Subject: Bug in AutoLoader.pm causing endless loop
From: Steffen Mueller
Date: Tue, 09 Jan 2007 19:15:36 +0100
Message-ID: <45A3DBC8.4010203@sneakemail.com>
Branch: perl
! lib/AutoLoader.pm


--
Slaven Rezic - slaven rezic de
babybike - routeplanner for cyclists in Berlin
handheld (e.g. Compaq iPAQ with Linux) version of bbbike
http://bbbike.sourceforge.net

Re: UTF-8-codierte Umlaute via print und warn ausgeben

am 10.08.2007 17:29:53 von hjp-usenet2

On 2007-08-09 19:27, Slaven Rezic wrote:
> "Peter J. Holzer" writes:
>> On 2007-08-08 18:33, Slaven Rezic wrote:
>> > "Peter J. Holzer" writes:
>> >> On 2007-08-07 19:58, Johannes v. Löwis wrote:
>> > [...]
>> >> Dazu musst Du feststellen, welches Encoding das verwendete Terminal
>> >> verwendet. Diese Information sollte man aus der Locale bekommen:
>> >
>> > Leider kann man sich auf diese Information nicht verlassen. Ich kann
>> > in meinem xterm per Menü UTF-8 ein- und ausschalten --- die Locale
>> > wird damit nicht geändert. Umgekehrt kann ich auch die LC_*- und
>> > LANG-Environment-Variablen ändern, ohne dass dies in der
>> > Terminaleinstellung reflektiert wird.
>>
>> Ja. Um Henry Spencer zu paraphrasieren: If you lie to the computer it
>> will get its revenge.
>
> Das kann schnell versehentlich passieren, z.B. indem man sich per ssh
> auf einen anderen Rechner einloggt. Typischerweise gehen die
> Locale-Variablen dabei verloren.

Das Grundproblem ist, dass es keine Möglichkeit gibt, das Terminal zu
fragen, welches Encoding es verwendet (zumindest keine zuverlässige).
Also muss der Mensch den Applikationen das über eine
Environment-Variable mitteilen. Das ist fehleranfällig. Dass diese
Environment-Variablen bis vor kurzem nicht über SSH übergeben werden
konnten, macht das ganze noch fehleranfälliger.

>> > Leider kann man sich auf diese Information nicht verlassen.

Man muss sich darauf verlassen, denn es gibt keine zuverlässigere
Möglichkeit, diese Information zu bekommen. Dafür, dass die Information
stimmt, muss der User (oder unter Umständen der Sysadmin) sorgen.

hp

--
_ | Peter J. Holzer | I know I'd be respectful of a pirate
|_|_) | Sysadmin WSR | with an emu on his shoulder.
| | | hjp@hjp.at |
__/ | http://www.hjp.at/ | -- Sam in "Freefall"

Re: UTF-8-codierte Umlaute via print und warn ausgeben

am 12.08.2007 21:11:53 von Johannes

Johannes v. Löwis wrote:
[...]
> : johannes@ford:~/bin$ cat bar.pl
> : #!/usr/bin/perl
> : binmode STDERR, ":encoding('cp850')";
> : johannes@ford:~/bin$ ./bar.pl
> : Segmentation fault (core dumped)
>
> Was dieser Code bei ActivePerl macht, werde ich morgen ausprobieren.

Er fuehrt auch zu einem Perl-Crash (Message-Box mit einer boesen
Fehlermeldung, die eine Adresse beinhaltet (Active Perl 5.8.8, Build
819)).

Unter Cygwin mit Perl 5.8.7 passierte uebrigens nichts derartiges.

Gruss
Johannes

Re: UTF-8-codierte Umlaute via print und warn ausgeben

am 12.08.2007 23:46:14 von hjp-usenet2

On 2007-08-09 20:38, Johannes v. Löwis wrote:
> Unter Ubuntu Linux 6.10 (Perl 5.8.8) habe ich uebrigens folgendes
> beobachtet:
>
>: johannes@ford:~/bin$ cat bar.pl
>: #!/usr/bin/perl
>: binmode STDERR, ":encoding('cp850')";
>: johannes@ford:~/bin$ ./bar.pl
>: Segmentation fault (core dumped)

Da habe ich eine Weile gebraucht, um das Problem zu sehen. Das muss

binmode STDERR, ":encoding(cp850)";

heißen.

hp


--
_ | Peter J. Holzer | I know I'd be respectful of a pirate
|_|_) | Sysadmin WSR | with an emu on his shoulder.
| | | hjp@hjp.at |
__/ | http://www.hjp.at/ | -- Sam in "Freefall"