Thread Zeichensatzproblem mit Š (15 answers)
Opened by bianca at 2019-06-07 19:07

haj
 2019-06-08 21:48
#190111 #190111
User since
2015-01-07
527 Artikel
BenutzerIn

user image
2019-06-08T17:38:34 bianca
Danke an haj und rosti aber ich weiß, dass es so funktioniert wie von euch gezeigt aber in meinem Script geht es nicht. Dort kommen die beiden Zeichen laut CPAN:Data::Dumper an, wie ich gezeigt habe aber ein und der selbe Regex reagiert nur auf das kleine š richtig. Warum nicht auch auf das große Š?


Danke für das Beispiel! Das ganze ist mir nun schon klar.

  • Du gibst in $name für š und Š die Byte-Werte im ISO-8859-15-Encoding an. Damit sind das für Perl, das Bytes nach ISO-8859-1 interpretiert, die Zeichen U+00A6 BROKEN BAR und U+00A8 DIAERESIS. Das ist schräg, könnte aber noch funktionieren, wenn Dein Notepad++ Dein Skript tatsächlich unter ISO-8859-15 abspeichern könnte, denn dann würde Perl in Deiner Regex š und Š genauso falsch interpretieren und die beiden Fehler würden sich gegenseitig aufheben.
  • Aber: Notepad++ kann Dein Skript nicht unter ISO-8859-15 abspeichern. In ISO-8859-15 gibt es kein ½. Zeichenkodierungen, die sowohl š und Š als auch '½' anbieten, sind - wir hatten das schon - die Windows Codepages 1250 und 1252. Der Verdacht, dass Notepad++ eines dieser Encodings als "ANSI" verwendet, ist also nicht von der Hand zu weisen.


Und nun schau' genau hin: Du hast ein U+00A8 DIAERESIS, ein '¨' in Deiner Regex. Und schon ist es weg, das ISO-LATIN-15-š. Das große hat einfach Pech gehabt. Du hast keinen BROKEN BAR in Deiner Regex.

Das Resultat bleibt übrigens das gleiche, wenn Notepad++ Dein Skript unter UTF-8 abspeicherst, Du aber kein use utf8; drin hast. Es gibt einen Satz von Zeichen, die bei UTF-8-Codierung einfach ein Byte 0xC2 vor den ISO-8859-1-Wert gestellt bekommen, und die DIAERESIS gehört dazu.

Ein einfacher Test wäre folgender: Nimm einfach das '¨' aus Deiner Regex raus. Wenn ich dann das Skript unter Windows-CP1252 abspeichere und laufen lasse, erhalte ich:
Code: (dl )
1
2
3
4
$VAR1 = [
16,
21
];

Wenn ich das unter UTF-8 abspeichere, dann - schwupp - ist die 16 wieder weg, auch ohne '¨' im regulären Ausdruck. Das liegt daran, dass sich das 'è' aus Deiner Regex in die zwei Bytes "\xc3\xa8" auflöst (es ist kein use utf8; aktiv) und somit auch Deine DIAERESIS eliminiert.

Oder, noch gemeiner: Schreibe den BROKEN BAR ¦ in Deine Regex. Schon wird auch das Š ordnungsgemäß (für bestimmte Werte von ordnungsgemäß) rausgefischt. Du hättest den Fehler gar nicht bemerkt, bis zum nächsten Kunden mit einem Sonderzeichen, das Du zufällig nicht drin hast. Gegenseitiges Aufheben von Fehlern ist eine der häufigsten Tücken bei der Behandlung von Zeichenkodierungen!

Magst Du solche Zufallsresultate? Wohl eher nein. Es gibt mehrere Ansätze, wie man's richtig macht. Hier meine Empfehlungen:

  • Vermeide Non-ASCII-Literale im Source-Code, wo immer es geht.
  • Es gibt in Perl diverse Möglichkeiten, jedes Unicode-Zeichen in ASCII auszudrücken. ISO-8859-15-Bytes zu verwenden, ist allerdings nicht richtig. Richtig wäre beispielsweise die Verwendung der Unicode-Codepoints: "\x{0160}" für Š und "\x{0161}" für š.
  • Wenn es nicht geht oder umständlich ist (so wie hier), dann speichere die Quelldatei in UTF-8-Codierung und setze use utf8;.
  • Decodiere alle Daten, die in Dein Programm reinkommen, sobald Du sie siehst (das hätte Dein früheres NBSP-Problem schon gar nicht entstehen lassen).

View full thread Zeichensatzproblem mit Š