locales mit der glibc

09/03/2012 - 18:36 von Markus Wichmann | Report spam
Hi all,

ich hab da mal eine Frage bezüglich der glibc und locales in Verbindung
mit UTF-8. Und zwar bin ich auf ein Problem mit isalpha() gestoßen. Ich
habe folgende Anwendung geschrieben:

#include <stdio.h>
#include <ctype.h>
#include <locale.h>

int main(void)
{
int c;

setlocale(LC_ALL, "");

while ((c = getchar()) != EOF)
{
if (isalpha(c)) puts("yes");
else puts("no");
}
return 0;
}

Wenn ich diese Anwendung jetzt mit LC_CTYPE=de_DE.UTF-8 ausführe
(genauer ist hier LANG=de_DE.UTF-8 und LC_CTYPE nicht besonders gesetzt,
nur LC_COLLATE steht auf C) passiert folgendes:

$ echo aà | ./test
yes
no
no
no

Aha. Das a ist ein alphabetisches Zeichen, die beiden Bytes vom à werden
auseinandergenommen und sind deswegen natürlich kein alphabetisches
Zeichen mehr und das Newline am Ende natürlich auch nicht.

Also hab ich das Programm veràndert:

#include <stdio.h>
#include <wctype.h>
#include <wchar.h>
#include <locale.h>

int main(void)
{
wint_t c;

setlocale(LC_ALL, "");

while ((c = getwchar()) != WEOF)
{
if (iswalpha(c)) puts("yes");
else puts("no");
}
return 0;
}

Jetzt funktioniert es wie gedacht:

$ echo aà | ./test
yes
yes
no

Genau was ich wollte!

Warum schreibe ich das? Nun, ich wollte eigentlich eine Kleinigkeit für
die Shell programmieren und benötigte dazu tr. Aber tr denkt trotz
meines Locales nicht, dass ein à ein alphabetisches Zeichen sei:

$ echo aà | tr -dc '[:alpha:]'; echo
a

Muss ich jetzt tr dahingehend bearbeiten, dass es alles, was es tut, nur
noch mit wint_t-Strings macht, oder kann man die glibc, ohne tr zu
patchen, anderweitig dazu überreden, dass ein à auch in UTF-8 ein
alphabetisches Zeichen ist?

Ciao,
Markus
 

Lesen sie die antworten

#1 Stefan Reuther
09/03/2012 - 20:08 | Warnen spam
Markus Wichmann wrote:
Nun, ich wollte eigentlich eine Kleinigkeit für
die Shell programmieren und benötigte dazu tr. Aber tr denkt trotz
meines Locales nicht, dass ein à ein alphabetisches Zeichen sei:

$ echo aà | tr -dc '[:alpha:]'; echo
a



tr kann kein multibyte, weder bei der OpenGroup:
<http://pubs.opengroup.org/onlinepub...tml>...
If any of the constructs result in multi-character collating elements,
tr will exclude, without a diagnostic, those multi-character elements
from the resulting array.
...noch bei GNU...
<http://www.gnu.org/software/coreuti...n.html>:
Currently tr fully supports only single-byte characters.

Muss ich jetzt tr dahingehend bearbeiten, dass es alles, was es tut, nur
noch mit wint_t-Strings macht, oder kann man die glibc, ohne tr zu
patchen, anderweitig dazu überreden, dass ein à auch in UTF-8 ein
alphabetisches Zeichen ist?



Ich hab gerade kein UTF-8-locale zum Testen da, aber es gibt ja außer
'tr' noch andere Programme, die 'tr -dc' ersetzen können. Perl sollte
definitiv UTF-8 können.


Stefan

Ähnliche fragen