framstag@fex: echo "x����z" | perl -ne 'print uc'
X����Z
framstag@fex: perl -e 'print uc("x����z\n")'
X����Z
framstag@fex: locale
LANG=en_US.ISO8859-1
LC_CTYPE="en_US.ISO8859-1"
LC_NUMERIC="en_US.ISO8859-1"
LC_TIME="en_US.ISO8859-1"
LC_COLLATE="en_US.ISO8859-1"
LC_MONETARY="en_US.ISO8859-1"
LC_MESSAGES="en_US.ISO8859-1"
LC_PAPER="en_US.ISO8859-1"
LC_NAME="en_US.ISO8859-1"
LC_ADDRESS="en_US.ISO8859-1"
LC_TELEPHONE="en_US.ISO8859-1"
LC_MEASUREMENT="en_US.ISO8859-1"
LC_IDENTIFICATION="en_US.ISO8859-1"
LC_ALL=
Ausserdem matcht \w ebenfalls nicht auf Umlaute, sondern nur auf ASCII.
Gibts was besseres als [\w�-�] um alphanumerische Latin1 Zeichen zu
matchen?
--
Ullrich Horlacher Informationssysteme und Serverbetrieb
Rechenzentrum E-Mail: horl...@rus.uni-stuttgart.de
Universitaet Stuttgart Tel: ++49-711-685-65868
Allmandring 30 Fax: ++49-711-682357
70550 Stuttgart (Germany) WWW: http://www.rus.uni-stuttgart.de/
> Ich dachte eigentlich bisher, dass die Funktionen uc() und lc() bei
> korrekt gesetztem locale auch auf Umlaute wirken?
> framstag@fex: echo "x����z" | perl -ne 'print uc'
> X����Z
> [...]
Du musst die Ein-/Ausgaben als UTF-8 deklarieren:
| [tim@passepartout ~]$ echo "x����z" | perl -CS -ne 'print uc'
| X����Z
| [tim@passepartout ~]$
Tim
$ echo "xᅵᅵᅵᅵz" | perl -Mlocale -ne 'print uc'
XᅵᅵᅵᅵZ
$ perl --version | head -n 2
This is perl, v5.10.0 built for i686-linux-thread-multi-64int-ld
$ locale
LANG=en_US.ISO_8859-15
LC_CTYPE="en_US.ISO_8859-15"
LC_NUMERIC="en_US.ISO_8859-15"
LC_TIME="en_US.ISO_8859-15"
LC_COLLATE=POSIX
LC_MONETARY="en_US.ISO_8859-15"
LC_MESSAGES="en_US.ISO_8859-15"
LC_ALL=
Explizit gesetzt sind nur LANG und LC_COLLATE. libc ist GNU libc
2.1.3. War auch schon bei deutlich ᅵlteren perl 5.x so:
$ echo "xᅵᅵᅵᅵz" | PERL5LIB= /usr/bin/perl5.00503 -Mlocale -ne 'print uc'
XᅵᅵᅵᅵZ
Mit UTF-8 klappte das damals aber noch nicht so einfach:
$ echo "xᅵᅵᅵᅵz" | recode latin9..UTF-8 | LANG=de_DE.UTF-8 \
PERL5LIB= /usr/bin/perl5.00503 -Mlocale -ne 'print uc' | \
recode UTF-8..latin9
XᅵᅵᅵᅵZ
Auf nem aktuellen Linux mit GNU libc 2.9 / gcc 4.3.2 / perl 5.10.0
ist's auch nicht anders:
$ echo "xᅵᅵᅵᅵz" | perl -ne 'print uc'
XᅵᅵᅵᅵZ
$ echo "xᅵᅵᅵᅵz" | perl -Mlocale -ne 'print uc'
XᅵᅵᅵᅵZ
HTH,
-dnh
--
Ein Hund denkt: Sie fᅵttern mich, sie sorgen fᅵr mich, sie streicheln
mich: das mᅵssen Gᅵtter sein.
Eine Katze denkt: Sie fᅵttern mich, sie sorgen fᅵr mich, sie streicheln
mich: ich muss ein Gott sein. -- Konni Scheller
Nein. Ich hab kein UTF-8, sondern ISO-Latin-1.
Nein, en_US.ISO8859-1 ist bei mir richtig.
TatatATAAA! Das wars :-)
Sie wirken auch ohne locale wenn Du sie auf einen Character-String
anwendest. Bei einem Byte-String wei� Perl (ohne Locale-Information) ja
nicht, was die Bytes bedeuten sollen.
>> > framstag@fex: echo "x����z" | perl -ne 'print uc'
>> > X����Z
>> > [...]
>>
>> Du musst die Ein-/Ausgaben als UTF-8 deklarieren:
>
> Nein. Ich hab kein UTF-8, sondern ISO-Latin-1.
Dann musst Du es als ISO-Latin-1 deklarieren.
Mantra der korrekten Behandlung von Text in Perl:
Decode input, encode output.
(Siehe binmode, Perl I/O Layer)
"use locale" habe ich vor vielen Jahren als unbrauchbar abgehakt, ich
kann mich aber nicht mehr erinnern, warum. Wenn ich (was kaum mehr
vorkommt, ist inzwischen fast alles UTF-8) locale-spezifisches Encoding
brauche, dann mache ich das so:
use I18N::Langinfo qw(langinfo CODESET);
$encoding = langinfo(CODESET);
binmode STDIN, ":encoding($encoding)";
binmode STDOUT, ":encoding($encoding)";
hp
Die genaue Schreibweise variiert, oft werden auch mehrere
akzeptiert. Zum Beispiel:
.ISO8859-1, ISO-8859-1, ISO_8859-1, iso8859-1 ...
oder
.ISO8859-15, ISO-8859-15, ISO_8859-15, iso8859-15, @euro ...
je nach Art/Version der (g)libc ... Man mᅵge sich aus der Ausgabe von
'locale -m' oder den Dateinamen aus 'ls /usr/share/i18n/charmaps/'
ohne .gz eine passende Schreibweise heraussuchen ;)
Wichtiger ist, daᅵ man perl auch mitteilt, daᅵ man gedenkt, auf die
locales zuzugreifen ;)
Peter Holzer's Methode gibt mir ᅵbrigens ein falsches Encoding:
$ perl -e 'use I18N::Langinfo qw(langinfo CODESET);
print langinfo(CODESET), "\n";'
ISO-8859-1
Peter? (nein, da ist keine 5 verlorengeganen).
Ich verwende hier aber seit ca. 2003 durchgᅵngig ISO-8859-15, und LANG
ist / die locales sind auch passend gesetzt.
Ich halte es fᅵr sinnvoll, per default die System-locale zu verwenden,
eben z.B. durch das einfache 'use locale;', und generell (bei Bedarf)
per binmode/open _gezielt_ das encoding fᅵr die einzulesenden bzw.
auszugebenden Daten zu setzen, wenn die Daten eben nicht "lokaler"
Herkunft sind ;)
-dnh, meist mit glibc-2.1.3, LANG=en_US.ISO-8859-15 und z.B. perl
5.10.0 unterwegs
--
Was macht denn einen Sysadmin schneller munter
als eine Katze auf der Tastatur? -- Mark-Oliver Wolter
Ist eventuell eine der LC_*-Variablen anders gesetzt?
Hier funktioniert es auf Debian:
% LANG=en_US.iso88591
% ./printencoding
ISO-8859-1
% LANG=de_AT@euro
% ./printencoding
ISO-8859-15
% LANG=greek
% ./printencoding
ISO-8859-7
und Redhat:
% LANG=de_AT.iso885915@euro
% ./printencoding
ISO-8859-15
% LANG=zh_CN.gb2312
% ./printencoding
GB2312
> Ich halte es f�r sinnvoll, per default die System-locale zu verwenden,
> eben z.B. durch das einfache 'use locale;', und generell (bei Bedarf)
> per binmode/open _gezielt_ das encoding f�r die einzulesenden bzw.
> auszugebenden Daten zu setzen, wenn die Daten eben nicht "lokaler"
> Herkunft sind ;)
>
> -dnh, meist mit glibc-2.1.3, LANG=en_US.ISO-8859-15 und z.B. perl
> 5.10.0 unterwegs
glibc-2.1.3? Im Ernst? Die Version war bei Redhat 6.2 dabei, ebenso wie
perl 5.005. D�rfte also gute 10 Jahre alt sein. Da w�rde ich nicht
ausschlie�en, dass die einige Bugs im Locale-Handling hat.
hp
Nein.
$ locale
LANG=en_US.ISO-8859-15
LC_CTYPE="en_US.ISO-8859-15"
LC_NUMERIC="en_US.ISO-8859-15"
LC_TIME="en_US.ISO-8859-15"
LC_COLLATE=POSIX
LC_MONETARY="en_US.ISO-8859-15"
LC_MESSAGES="en_US.ISO-8859-15"
LC_ALL=
Explizit gesetzt sind nur LANG und LC_COLLATE.
[..]
>> -dnh, meist mit glibc-2.1.3, LANG=en_US.ISO-8859-15 und z.B. perl
>> 5.10.0 unterwegs
>
> glibc-2.1.3? Im Ernst? Die Version war bei Redhat 6.2 dabei, ebenso wie
> perl 5.005. Dᅵrfte also gute 10 Jahre alt sein. Da wᅵrde ich nicht
> ausschlieᅵen, dass die einige Bugs im Locale-Handling hat.
Jup und jup. Das wird's sein. Das System hab ich Sommer '99
installiert, noch mit glibc-2.1.2, nach ner Spielerei zum glibc-Update
(miᅵglᅵckt) hab ich dann die glibc-2.1.3 der SUSE 6.4 installiert ;)
Wie man schon am Perl und Kernel 2.4.37 sieht, aktualisiere ich aber
vieles ;)
Anderes System mit perl 5.10.0 und ner glibc-2.9:
$ locale
LANG=en_US.iso885915
LC_CTYPE="en_US.iso885915"
LC_NUMERIC="en_US.iso885915"
LC_TIME="en_US.iso885915"
LC_COLLATE=POSIX
LC_MONETARY="en_US.iso885915"
LC_MESSAGES="en_US.iso885915"
LC_PAPER="en_US.iso885915"
LC_NAME="en_US.iso885915"
LC_ADDRESS="en_US.iso885915"
LC_TELEPHONE="en_US.iso885915"
LC_MEASUREMENT="en_US.iso885915"
LC_IDENTIFICATION="en_US.iso885915"
LC_ALL=
$ perl -e 'use I18N::Langinfo qw(langinfo CODESET);
print langinfo(CODESET), "\n";'
ISO-8859-15
Explizit gesetzt LANG und LC_COLLATE. Passt. Vermutlich rechnet eben
keiner (zu Recht) mit so ner Kombination von perl und glibc
bzw. I18N::Langinfo fehlen die dafᅵr erforderlichen Sonderlocken.
Danke fᅵr's mitdenken!
-dnh, *das mit der glibc-Abhᅵngigkeit im Hinterkopf behalt*
--
Dinner not ready...(A)bort (R)etry (P)izza
Im Zweifelsfall verlasse ich mich lieber auf die Ausgabe von locale -a
als auf Doku.
hp
Was auch immer dieser letzte Satz bedeuten mag.
> Wobei allerdings genaugenommen beides nicht zu vergleichen ist. locale -a
> gibt die Locales aus, die wirklich vorhanden (generiert) sind, w�hrend die
> Datei alle m�glichen enth�lt.
Das ist der Punkt. locale -a gibt mir die Locales aus, die auf diesem
System tats�chlich installiert sind. Wenn ich einen dieser Werte
verwende, funktioniert das sicher. Auf jeder Linux-Distribution, auf
HP-UX, Solaris, AIX, ...
Ein /usr/share/i18n/SUPPORTED hingegen gibt es weder unter HP-UX noch
unter RedHat Linux - das scheint Debian-spezifisch zu sein.
> locale -a gibt bei mir die Namen der vorhandenen locales �brigens
> ausnahmslos ohne Bindestriche aus. Dies legt die Vermutung nahe, da� diese
> einfach ignoriert werden
Mit der Vermutung d�rftest Du recht haben.
LANG=de_AT.U-T-F--8
funktioniert jedenfalls auch.
> Dann w�re Deine Angabe wohl auch richtig,
Die ist auf diesem System ganz sicher richtig, weil locale -a sie so
ausgibt. Also muss es auf diesem System eine Locale dieses Namens geben.
Hingegen steht "de_DE@euro" zwar im SUPPORTED-File, aber diese Locale
gibt es bei mir nicht (weil ich sie nicht generiert habe).
> wobei ich es mit Bindestrichen leichter lesbar finde.
Da stimme ich Dir zu.
hp