592 Stimmen

Warum vermeidet das moderne Perl standardmäßig UTF-8?

Ich frage mich, warum die meisten modernen Lösungen, die mit Perl entwickelt wurden, nicht die UTF-8 standardmäßig.

Ich weiß, dass es viele Legacy-Probleme für Kern-Perl-Skripte gibt, bei denen es Dinge kaputt machen kann. Aber aus meiner Sicht ist es in den 21 st Jahrhunderts, sollten große neue Projekte (oder Projekte mit einer großen Perspektive) ihre Software von Grund auf UTF-8-fest machen. Dennoch sehe ich nicht, dass dies geschieht. Zum Beispiel, Elch ermöglicht strenge und Warnungen, aber nicht Unicode . Modern::Perl reduziert auch Boilerplate, aber keine UTF-8-Behandlung.

Warum? Gibt es Gründe, UTF-8 in modernen Perl-Projekten im Jahr 2011 zu vermeiden?


Der Kommentar von @tchrist wurde zu lang, also füge ich ihn hier hinzu.

Es scheint, dass ich mich nicht klar ausgedrückt habe. Lassen Sie mich versuchen, einige Dinge hinzuzufügen.

tchrist und ich sehen die Situation ziemlich ähnlich, aber unsere Schlussfolgerungen sind völlig gegensätzlich. Ich stimme zu, die Situation mit Unicode ist kompliziert, aber das ist der Grund, warum wir (Perl-Benutzer und Programmierer) eine Schicht (oder ein Pragma) brauchen, die den Umgang mit UTF-8 so einfach macht, wie er heutzutage sein muss.

tchrist auf zu viele Aspekte hinweisen, um sie zu behandeln, werde ich tagelang oder sogar wochenlang lesen und darüber nachdenken. Doch das ist nicht mein Anliegen. tchrist versucht zu beweisen, dass es nicht nur einen einzigen Weg gibt, "UTF-8 zu aktivieren". Ich habe nicht so viel Wissen, um das zu bestreiten. Also bleibe ich bei Live-Beispielen.

Ich habe herumgespielt mit Rakudo und UTF-8 war einfach da wie ich es brauchte . Ich hatte keine Probleme, es hat einfach funktioniert. Vielleicht gibt es einige Einschränkungen irgendwo tiefer, aber am Anfang funktionierte alles, was ich getestet habe, wie ich erwartet hatte.

Sollte das nicht auch ein Ziel in modernem Perl 5 sein? Ich betone es noch mehr: Ich schlage nicht UTF-8 als Standard-Zeichensatz für den Perl-Kern vor, sondern die Möglichkeit, ihn zu aktivieren mit einem Ruck für diejenigen, die sich entwickeln nouveau Projekte.

Ein weiteres Beispiel, aber mit einem eher negativen Ton. Frameworks sollen die Entwicklung erleichtern. Vor einigen Jahren habe ich Web-Frameworks ausprobiert, sie aber einfach weggeworfen, weil "UTF-8 aktivieren" so obskur war. Ich habe nicht herausgefunden, wie und wo ich die Unicode-Unterstützung einbinden kann. Es war so zeitaufwändig, dass ich es einfacher fand, den alten Weg zu gehen. Jetzt habe ich gesehen, dass es hier ein Kopfgeld gibt, um das gleiche Problem zu lösen mit Maurer 2: Wie kann man Mason2 UTF-8 sauber machen? . Es handelt sich also um ein ziemlich neues Framework, aber seine Verwendung mit UTF-8 erfordert tiefes Wissen über seine Interna. Es ist wie ein großes rotes Schild: STOP, benutze mich nicht!

Ich mag Perl sehr. Aber der Umgang mit Unicode ist schmerzhaft. Ich renne immer noch gegen Wände. Irgendwie tchrist ist richtig und beantwortet meine Fragen: neue Projekte ziehen UTF-8 nicht an, weil es in Perl 5 zu kompliziert ist.

4 Stimmen

Hallo Leute - es gibt ein paar Anzeichen, die auf diese Kommentare hinweisen. Ich habe einen Schnappschuss der Kommentare hier gemacht und sie in diesen Chatroom gestellt, wo ihr die Diskussion weiterführen könnt: chat.stackoverflow.com/rooms/846/

16 Stimmen

Es tut mir leid, aber ich stimme @tchrist zu - UTF-8 ist extrem schwierig. Es gibt kein Framework oder Tool, das einfach "einen Schalter umlegt" und es dann richtig handhabt. Das ist etwas, worüber man direkt nachdenken muss, wenn man seine Anwendung entwirft - nichts, was irgendein Framework oder eine Sprache für einen erledigen kann. Wenn rakudo nur zufällig für Sie funktioniert hat, waren Sie nicht abenteuerlich genug mit Ihren Testfällen -- denn es wird mehrere der Beispiele in @tchrist's Antwort nehmen und dann ausschlachten.

12 Stimmen

Was genau erhoffen Sie sich von Moose oder Modern::Perl? Auf magische Weise zufällig kodierte Zeichendaten in Dateien und Datenbanken wieder in gültige Daten verwandeln?

1195voto

tchrist Punkte 76479

:

  1. Stellen Sie Ihr PERL_UNICODE nehmbar an AS . Dies macht alle Perl-Skripte dekodieren @ARGV als UTF8-Zeichenfolgen und setzt die Kodierung aller drei Programme stdin, stdout und stderr auf UTF8. Beides sind globale Effekte, keine lexikalischen.

  2. Am Anfang Ihrer Quelldatei (Programm, Modul, Bibliothek, do hickey), weisen Sie darauf hin, dass Sie Perl Version 5.12 oder besser verwenden:

    use v5.12;  # minimal for unicode string feature
    use v5.14;  # optimal for unicode string feature
  3. Aktivieren Sie Warnungen, da die vorherige Erklärung nur Strictures und Features aktiviert, nicht aber Warnungen. Ich schlage außerdem vor, Unicode-Warnungen in Ausnahmen umzuwandeln, also verwenden Sie diese beiden Zeilen, nicht nur eine davon. Beachten Sie jedoch, dass unter v5.14 die utf8 Warnklasse umfasst drei weitere Unterwarnungen, die alle separat aktiviert werden können: nonchar , surrogate y non_unicode . Diese möchten Sie vielleicht stärker kontrollieren.

    use warnings;
    use warnings qw( FATAL utf8 );
  4. Deklarieren Sie, dass diese Quelleinheit als UTF8 kodiert ist. Obwohl dieses Pragma früher auch für andere Zwecke verwendet wurde, dient es jetzt nur noch diesem einen Zweck und keinem anderen:

    use utf8;
  5. Erklären Sie, dass alles, was einen Filehandle öffnet innerhalb dieses lexikalischen Bereichs, aber nicht anderswo ist es, anzunehmen, dass der Stream in UTF8 kodiert ist, es sei denn, Sie sagen ihm etwas anderes. Auf diese Weise beeinflussen Sie nicht den Code anderer Module oder Programme.

    use open qw( :encoding(UTF-8) :std );
  6. Aktivieren Sie benannte Zeichen über \N{CHARNAME} .

    use charnames qw( :full :short );
  7. Wenn Sie eine DATA handle, müssen Sie seine Kodierung explizit festlegen. Wenn Sie wollen, dass dies UTF8 ist, dann sagen Sie:

    binmode(DATA, ":encoding(UTF-8)");

Es gibt natürlich noch viele andere Dinge, mit denen man sich beschäftigen kann, aber diese reichen aus, um sich dem Staatsziel "alles mit UTF8 zu machen" anzunähern, wenn auch in einem etwas abgeschwächten Sinne.

Ein weiteres Pragma, das allerdings nicht mit Unicode zusammenhängt, ist:

      use autodie;

Es wird dringend empfohlen.



Meine eigenen Standardformulierungen sehen heutzutage in der Regel so aus:

use 5.014;

use utf8;
use strict;
use autodie;
use warnings; 
use warnings    qw< FATAL  utf8     >;
use open        qw< :std  :utf8     >;
use charnames   qw< :full >;
use feature     qw< unicode_strings >;

use File::Basename      qw< basename >;
use Carp                qw< carp croak confess cluck >;
use Encode              qw< encode decode >;
use Unicode::Normalize  qw< NFD NFC >;

END { close STDOUT }

if (grep /\P{ASCII}/ => @ARGV) { 
   @ARGV = map { decode("UTF-8", $_) } @ARGV;
}

$0 = basename($0);  # shorter messages
$| = 1;

binmode(DATA, ":utf8");

# give a full stack dump on any untrapped exceptions
local $SIG{__DIE__} = sub {
    confess "Uncaught exception: @_" unless $^S;
};

# now promote run-time warnings into stack-dumped
#   exceptions *unless* we're in an try block, in
#   which case just cluck the stack dump instead
local $SIG{__WARN__} = sub {
    if ($^S) { cluck   "Trapped warning: @_" } 
    else     { confess "Deadly warning: @_"  }
};

while (<>)  {
    chomp;
    $_ = NFD($_);
    ...
} continue {
    say NFC($_);
}

__END__


Mit der Aussage "Perl sollte [ irgendwie! Unicode standardmäßig aktivieren" ist nicht einmal ansatzweise so viel, dass es in seltenen und isolierten Fällen auch nur annähernd nützlich wäre. Unicode ist viel, viel mehr als nur ein größeres Zeichenrepertoire; es geht auch darum, wie diese Zeichen alle auf viele, viele Arten zusammenwirken.

Selbst die einfältigen Minimalmaßnahmen, von denen (einige) Leute zu glauben scheinen, dass sie sie wollen, führen garantiert dazu, dass Millionen von Codezeilen kaputt gehen, Code, der keine Chance hat, auf Ihre schicke neue Version "aufzurüsten". Schöne neue Welt Modernität.

Es ist viel viel viel viel komplizierter, als die Leute vorgeben. Ich habe in den letzten Jahren sehr, sehr viel darüber nachgedacht. Ich würde mich freuen, wenn man mir zeigen würde, dass ich falsch liege. Aber ich glaube nicht, dass ich das tue. Unicode ist grundsätzlich komplexer als das Modell, das Sie ihm aufzwingen wollen, und es gibt hier eine Komplexität, die Sie niemals unter den Teppich kehren können. Wenn Sie das versuchen, machen Sie entweder Ihren eigenen Code kaputt oder den von jemand anderem. Irgendwann muss man sich einfach überwinden und lernen, worum es bei Unicode geht. Man kann nicht so tun, als sei es etwas, was es nicht ist.

tut alles, um Unicode einfach zu machen, weit mehr als alles andere, was ich je benutzt habe. Wenn Sie das schlecht finden, probieren Sie eine Zeit lang etwas anderes aus. Dann kommen Sie zurück: Entweder sind Sie in eine bessere Welt zurückgekehrt, oder Sie bringen Wissen über dieselbe mit, so dass wir Ihr neues Wissen nutzen können, um diese Dinge besser zu machen.



Zumindest gibt es einige Dinge, die erforderlich zu sein scheinen, um "Unicode standardmäßig zu aktivieren", wie Sie es ausdrücken:

  1. Der gesamte Quellcode sollte standardmäßig in UTF-8 vorliegen. Sie können das mit use utf8 o export PERL5OPTS=-Mutf8 .

  2. Die DATA handle sollte UTF-8 sein. Sie müssen dies für jedes Paket einzeln tun, wie in binmode(DATA, ":encoding(UTF-8)") .

  3. Programmargumente für Skripte sollten standardmäßig als UTF-8 verstanden werden. export PERL_UNICODE=A , oder perl -CA , oder export PERL5OPTS=-CA .

  4. Die Standardeingabe-, -ausgabe- und -fehlerströme sollten standardmäßig auf UTF-8 eingestellt sein. export PERL_UNICODE=S für alle von ihnen oder I , O und/oder E nur für einige von ihnen. Das ist wie perl -CS .

  5. Alle anderen Handles, die von geöffnet werden, sollten als UTF-8 betrachtet werden, sofern nicht anders angegeben; export PERL_UNICODE=D oder mit i y o für bestimmte von ihnen; export PERL5OPTS=-CD funktionieren würde. Das macht -CSAD für alle von ihnen.

  6. Decken Sie beide Grundlagen und alle Streams ab, die Sie mit export PERL5OPTS=-Mopen=:utf8,:std . Siehe Einmalige Bewertung .

  7. Sie wollen keine UTF-8-Kodierungsfehler übersehen. Versuchen Sie export PERL5OPTS=-Mwarnings=FATAL,utf8 . Und stellen Sie sicher, dass Ihre Eingabeströme immer binmode d bis :encoding(UTF-8) nicht nur für :utf8 .

  8. Unter Codepunkten zwischen 128-255 sind die entsprechenden Unicode-Codepunkte zu verstehen, nicht nur unproperierte Binärwerte. use feature "unicode_strings" o export PERL5OPTS=-Mfeature=unicode_strings . Das macht uc("\xDF") eq "SS" y "\xE9" =~ /\w/ . Eine einfache export PERL5OPTS=-Mv5.12 oder besser ist, wird auch das bekommen.

  9. Benannte Unicode-Zeichen sind nicht standardmäßig aktiviert, also fügen Sie export PERL5OPTS=-Mcharnames=:full,:short,latin,greek oder ähnliches. Siehe uninames y tcgrep .

  10. Sie benötigen fast immer Zugriff auf die Funktionen von die Norm Unicode::Normaliz Modul verschiedene Arten von Zersetzungen. export PERL5OPTS=-MUnicode::Normalize=NFD,NFKD,NFC,NFKD und dann immer eingehende Daten über NFD und ausgehende Daten über NFC laufen lassen. Es gibt noch keine E/A-Schicht für diese, die mir bekannt ist, aber siehe nfc , nfd , nfkd y nfkc .

  11. String-Vergleiche bei Verwendung von eq , ne , lc , cmp , sort , &c&cc sind immer falsch. Also statt @a = sort @b benötigen Sie @a = Unicode::Collate->new->sort(@b) . Sie können das auch zu Ihrem export PERL5OPTS=-MUnicode::Collate . Sie können den Schlüssel für binäre Vergleiche zwischenspeichern.

  12. Einbauten wie printf y write mit Unicode-Daten das Falsche tun. Sie müssen verwenden die Unicode::GCString Modul für erstere, und sowohl das als auch die Unicode::LineBreak Modul auch für letztere. Siehe uwc y unifmt .

  13. Wenn Sie möchten, dass sie als ganze Zahlen zählen, dann müssen Sie Ihre \d+ Erfasst durch die Unicode::UCD::num Funktion weil 's eingebaut atoi (3) ist derzeit nicht clever genug.

  14. Sie werden Probleme mit dem Dateisystem auf Dateisystemen haben. Einige Dateisysteme erzwingen stillschweigend eine Konvertierung nach NFC; andere erzwingen stillschweigend eine Konvertierung nach NFD. Und wieder andere machen etwas anderes. Einige ignorieren die Angelegenheit sogar ganz, was zu noch größeren Problemen führt. Sie müssen also Ihre eigene NFC/NFD-Behandlung durchführen, um vernünftig zu bleiben.

  15. Ihr gesamter Code, der a-z o A-Z und dergleichen MUSS GEÄNDERT WERDEN einschließlich m// , s/// y tr/// . Das sollte ein schrilles Zeichen dafür sein, dass Ihr Code fehlerhaft ist. Aber es ist nicht klar, wie er sich ändern muss. Die richtigen Eigenschaften zu finden und ihre Zusammenhänge zu verstehen, ist schwieriger, als Sie vielleicht denken. Ich verwende unichars y uniprops jeden einzelnen Tag.

  16. Code, der die \p{Lu} ist fast genauso falsch wie Code, der [A-Za-z] . Sie müssen Folgendes verwenden \p{Upper} stattdessen und kennen den Grund dafür. Ja, \p{Lowercase} y \p{Lower} sind verschieden von \p{Ll} y \p{Lowercase_Letter} .

  17. Code, der die [a-zA-Z] ist noch schlimmer. Und es kann nicht verwenden \pL o \p{Letter} ; es muss verwendet werden \p{Alphabetic} . Nicht alle Alphabete sind Buchstaben, wissen Sie!

  18. Wenn Sie nach Variablen mit /[\$\@\%]\w+/ dann haben Sie ein Problem. Sie müssen suchen /[\$\@\%]\p{IDS}\p{IDC}*/ und selbst dabei werden die Interpunktionsvariablen oder Paketvariablen nicht berücksichtigt.

  19. Wenn Sie auf Leerzeichen prüfen, sollten Sie wählen zwischen \h y \v je nachdem. Und Sie sollten niemals \s da sie BEDEUTET NICHT [\h\v] Entgegen der landläufigen Meinung.

  20. Wenn Sie Folgendes verwenden \n für eine Linienbegrenzung, oder sogar \r\n dann machen Sie es falsch. Sie müssen verwenden \R was nicht dasselbe ist!

  21. Wenn Sie nicht wissen, wann und ob Sie anrufen sollen Unicode::Stringprep dann sollten Sie besser lernen.

  22. Vergleiche ohne Berücksichtigung der Groß-/Kleinschreibung müssen prüfen, ob es sich bei zwei Dingen um dieselben Buchstaben handelt, unabhängig von ihren diakritischen Zeichen und dergleichen. Der einfachste Weg, dies zu tun, ist mit der Standard Unicode::Collate Modul. Unicode::Collate->new(level => 1)->cmp($a, $b) . Außerdem gibt es eq Methoden und dergleichen, und Sie sollten sich wahrscheinlich über die match y substr auch Methoden. Diese haben deutliche Vorteile gegenüber den Einbauten.

  23. Manchmal reicht das noch nicht aus, und Sie brauchen das Unicode::Collate::Locale Modul stattdessen, wie in Unicode::Collate::Locale->new(locale => "de__phonebook", level => 1)->cmp($a, $b) stattdessen. Bedenken Sie das Unicode::Collate::->new(level => 1)->eq("d", "ð") ist wahr, aber Unicode::Collate::Locale->new(locale=>"is",level => 1)->eq("d", " ð") falsch ist. In ähnlicher Weise sind "ae" und "æ" eq wenn Sie keine Gebietsschemata verwenden, oder wenn Sie das englische Gebietsschema verwenden, aber im isländischen Gebietsschema sind sie anders. Was nun? Das ist schwierig, sage ich Ihnen. Sie können spielen mit ucsort um einige dieser Dinge auszuprobieren.

  24. Überlegen Sie, wie Sie das Muster CVCV (Konsonant, Vokal, Konsonant, Vokal) in der Zeichenfolge " niño ". Seine NFD-Form - die Sie besser nicht vergessen hätten - wird zu "nin \x {303}o". Was werden Sie jetzt tun? Selbst die Behauptung, ein Vokal sei [aeiou] (was übrigens falsch ist), werden Sie nicht in der Lage sein, etwas zu tun wie (?=[aeiou])\X) auch nicht, denn selbst in der NFD ist ein Codepunkt wie 'ø' zersetzt sich nicht ! Mit dem UCA-Vergleich, den ich Ihnen soeben gezeigt habe, wird er jedoch gleich einem "o" getestet. Sie können sich nicht auf die NFD verlassen, Sie müssen sich auf die UCA verlassen.



Und das ist noch nicht alles. Es gibt eine Million falscher Annahmen, die die Leute über Unicode machen. Solange sie diese Dinge nicht verstehen, wird ihr Code fehlerhaft sein.

  1. Code, der davon ausgeht, dass er eine Textdatei öffnen kann, ohne die Kodierung anzugeben, ist fehlerhaft.

  2. Code, der davon ausgeht, dass die Standardkodierung eine Art nativer Plattformkodierung ist, ist fehlerhaft.

  3. Code, der davon ausgeht, dass Webseiten in Japanisch oder Chinesisch in UTF16 weniger Platz benötigen als in UTF8, ist falsch.

  4. Code, der davon ausgeht, dass Perl intern UTF8 verwendet, ist falsch.

  5. Code, der davon ausgeht, dass Kodierungsfehler immer eine Ausnahme auslösen, ist falsch.

  6. Code, der davon ausgeht, dass Perl-Codepunkte auf 0x10_FFFF begrenzt sind, ist falsch.

  7. Code, der davon ausgeht, dass Sie die $/ zu etwas, das mit jedem gültigen Zeilentrennzeichen funktioniert, ist falsch.

  8. Code, der bei der Groß-/Kleinschreibung von der Gleichheit des Umlaufs ausgeht, wie lc(uc($s)) eq $s o uc(lc($s)) eq $s ist völlig kaputt und falsch. Bedenken Sie, dass die uc("") y uc("") sind beide "" mais lc("") kann unmöglich beides zurückgeben.

  9. Code, der davon ausgeht, dass zu jedem klein geschriebenen Codepunkt auch ein groß geschriebener gehört oder umgekehrt, ist fehlerhaft. Zum Beispiel, "ª" ist ein Kleinbuchstabe ohne Großbuchstaben, während beide "" y "" sind zwar Buchstaben, aber keine Kleinbuchstaben; beide sind jedoch Kleinbuchstaben ohne entsprechende Großbuchstaben. Haben Sie das verstanden? Sie sind no \p{Lowercase_Letter} obwohl sie beide \p{etter} y \p{Lowercase} .

  10. Code, der davon ausgeht, dass eine Änderung der Groß-/Kleinschreibung die Länge der Zeichenkette nicht ändert, ist fehlerhaft.

  11. Code, der davon ausgeht, dass es nur zwei Fälle gibt, ist fehlerhaft. Es gibt auch titlecase.

  12. Code, der davon ausgeht, dass nur Buchstaben Groß- und Kleinschreibung haben, ist fehlerhaft. Es stellt sich heraus, dass nicht nur Buchstaben, sondern auch Zahlen, Symbole und sogar Zeichen Groß- und Kleinschreibung haben. Eine Änderung der Groß- und Kleinschreibung kann sogar dazu führen, dass etwas seine allgemeine Hauptkategorie ändert, wie z. B. ein \p{Mark} die sich in eine \p{Letter} . Es kann auch von einem Skript zu einem anderen wechseln.

  13. Code, der davon ausgeht, dass der Fall niemals ortsabhängig ist, ist fehlerhaft.

  14. Code, der davon ausgeht, dass Unicode einen Scheiß auf POSIX-Sprachumgebungen gibt, ist kaputt.

  15. Ein Code, der davon ausgeht, dass man diakritische Zeichen entfernen kann, um an die Basis-ASCII-Buchstaben zu gelangen, ist böse, still, kaputt, hirngeschädigt, falsch und rechtfertigt die Todesstrafe.

  16. Code, der davon ausgeht, dass diakritische Zeichen \p{Diacritic} und Marken \p{Mark} sind, ist das Gleiche kaputt.

  17. Code, der davon ausgeht \p{GC=Dash_Punctuation} deckt so viel wie \p{Dash} gebrochen ist.

  18. Code, der davon ausgeht, dass Bindestriche, Bindestriche und Minuszeichen dasselbe sind oder dass es von jedem nur eines gibt, ist fehlerhaft und falsch.

  19. Code, der davon ausgeht, dass jeder Codepunkt nicht mehr als eine Druckspalte beansprucht, ist fehlerhaft.

  20. Code, der davon ausgeht, dass alle \p{Mark} Zeichen keine Druckspalten beanspruchen, ist fehlerhaft.

  21. Code, der davon ausgeht, dass Zeichen, die gleich aussehen sind Gleiches ist kaputt.

  22. Code, der davon ausgeht, dass Zeichen, die no gleich aussehen, sind no Gleiches ist kaputt.

  23. Code, der davon ausgeht, dass die Anzahl der Codepunkte in einer Reihe begrenzt ist und nur ein \X übereinstimmen kann, ist falsch.

  24. Code, der davon ausgeht \X kann niemals mit einer \p{Mark} Charakter ist falsch.

  25. Code, der davon ausgeht, dass \X kann niemals zwei Nicht \p{Mark} Zeichen falsch ist.

  26. Code, der davon ausgeht, dass er nicht mit "\x{FFFF}" ist falsch.

  27. Code, der davon ausgeht, dass ein Nicht-BMP-Codepunkt, der zwei UTF-16-Codeeinheiten (Surrogate) erfordert, in zwei separate UTF-8-Zeichen kodiert wird, eines pro Codeeinheit, ist falsch. Das ist nicht der Fall: Er kodiert in einen einzigen Codepunkt.

  28. Code, der von UTF16 oder UTF32 mit führenden BOMs in UTF8 transkodiert, ist kaputt, wenn er ein BOM an den Anfang des resultierenden UTF-8 setzt. Das ist so dumm, dass dem Ingenieur die Augenlider entfernt werden sollten.

  29. Code, der davon ausgeht, dass CESU-8 eine gültige UTF-Kodierung ist, ist falsch. Ebenso ist Code, der die Kodierung von U+0000 als "\xC0\x80" UTF-8 ist kaputt und falsch. Diese Jungs verdienen auch die Augenlid-Behandlung.

  30. Code, der Zeichen wie > zeigt immer nach rechts und < immer nach links zeigt, ist falsch - weil sie es in Wirklichkeit nicht tut.

  31. Code, der davon ausgeht, dass Sie bei der ersten Ausgabe eines Zeichens X und dann Zeichen Y dass diese als XY ist falsch. Manchmal tun sie es nicht.

  32. Code, der davon ausgeht, dass ASCII gut genug ist, um Englisch richtig zu schreiben, ist dumm, kurzsichtig, ungebildet, kaputt, böse und falsch. Ab mit ihren Köpfen! Wenn Ihnen das zu extrem erscheint, können wir einen Kompromiss finden: Ab jetzt dürfen sie nur noch mit dem großen Zeh eines Fußes tippen. (Der Rest wird mit Klebeband abgeklebt.)

  33. Code, der davon ausgeht, dass alle \p{Math} Codepunkte sichtbare Zeichen sind, ist falsch.

  34. Code, der davon ausgeht \w nur Buchstaben, Ziffern und Unterstriche enthält, ist falsch.

  35. Code, der davon ausgeht, dass ^ y ~ Interpunktionszeichen sind, ist falsch.

  36. Code, der davon ausgeht, dass ü hat einen Umlaut ist falsch.

  37. Code, der Dinge glaubt wie keine Buchstaben enthalten, ist falsch.

  38. Code, der glaubt \p{InLatin} ist dasselbe wie \p{Latin} ist abscheulich gebrochen.

  39. Code, die glauben, dass \p{InLatin} fast immer nützlich ist, ist mit Sicherheit falsch.

  40. Code, der davon ausgeht, dass angesichts $FIRST_LETTER als erster Buchstabe in einem Alphabet und $LAST_LETTER wie der letzte Buchstabe des Alphabets, dass [${FIRST_LETTER}-${LAST_LETTER}] irgendeine Bedeutung hat, ist fast immer völlig kaputt, falsch und sinnlos.

  41. Ein Code, der glaubt, dass der Name einer Person nur bestimmte Zeichen enthalten darf, ist dumm, beleidigend und falsch.

  42. Code, der versucht, Unicode auf ASCII zu reduzieren, ist nicht nur falsch, sein Urheber sollte nie wieder in der Programmierung arbeiten dürfen. Punkt. Ich bin mir nicht einmal sicher, ob es ihnen erlaubt sein sollte, wieder zu sehen, da es ihnen bisher offensichtlich nicht viel genützt hat.

  43. Code, der glaubt, es gäbe eine Möglichkeit, so zu tun, als gäbe es keine Textdatei-Codierungen, ist kaputt und gefährlich. Man könnte auch gleich das andere Auge ausstechen.

  44. Code zur Umwandlung unbekannter Zeichen in ? ist kaputt, dumm, hirnverbrannt und steht im Widerspruch zur Standardempfehlung, die besagt DAS NICHT ZU TUN! RTFM, warum nicht.

  45. Code, der glaubt, die Kodierung einer unmarkierten Textdatei zuverlässig erraten zu können, macht sich einer fatalen Mischung aus Hybris und Naivität schuldig, die nur ein Blitzschlag von Zeus beheben kann.

  46. Code, von dem Sie glauben, dass Sie ihn verwenden können printf Breiten zum Auffüllen und Ausrichten von Unicode-Daten ist fehlerhaft und falsch.

  47. Code, der nach erfolgreicher Erstellung einer Datei mit einem bestimmten Namen glaubt, dass bei der Ausführung von ls o readdir in dem sie umgebenden Verzeichnis suchen, werden Sie feststellen, dass die Datei mit dem Namen, unter dem Sie sie erstellt haben, fehlerhaft, kaputt und falsch ist. Lassen Sie sich davon nicht überraschen!

  48. Code, der glaubt, dass UTF-16 eine Kodierung mit fester Breite ist, ist dumm, kaputt und falsch. Entziehen Sie ihnen die Programmierlizenz.

  49. Code, der Codepunkte aus einer Ebene einen Deut anders behandelt als solche aus einer anderen Ebene, ist ipso facto kaputt und falsch. Geh wieder zur Schule.

  50. Code, der glaubt, dass Dinge wie /s/i kann nur mit "S" o "s" kaputt und falsch ist. Sie werden überrascht sein.

  51. Code, der die \PM\pM* um Graphem-Cluster zu finden, anstatt mit \X ist kaputt und falsch.

  52. Menschen, die in die ASCII-Welt zurückkehren wollen, sollten von ganzem Herzen dazu ermutigt werden, und zu Ehren ihres glorreichen Upgrades sollten sie mit kostenlos mit einer vor-elektrischen Handschreibmaschine für alle ihre Dateneingaben. Nachrichten an sie sollten über einen s-Telegrafen mit 40 Zeichen pro Zeile gesendet und von einem Kurier persönlich zugestellt werden. STOPP.



Ich weiß nicht, wie viel mehr "Standard-Unicode in" Sie bekommen können als das, was ich geschrieben habe. Nun, ja, ich weiß es: Sie sollten Folgendes verwenden Unicode::Collate y Unicode::LineBreak auch. Und wahrscheinlich noch mehr.

Wie Sie sehen, gibt es viel zu viele Unicode-Dinge, die Sie wirklich tun Sorgen machen müssen, dass es zu immer gibt es so etwas wie "standardmäßig auf Unicode".

Sie werden feststellen, genau wie wir damals in 5.8, dass es einfach unmöglich ist, all diese Dinge einem Code aufzuerlegen, der nicht von Anfang an so konzipiert wurde, dass er sie berücksichtigt. Ihr wohlmeinender Egoismus hat gerade die ganze Welt zerstört.

Und selbst wenn Sie das tun, gibt es immer noch kritische Punkte, die viel Überlegung erfordern, um sie richtig zu machen. Es gibt keinen Schalter, den man umlegen kann. Nichts als Gehirn, und ich meine echtes Gehirn reicht hier aus. Es gibt verdammt viel, was man lernen muss. Abgesehen vom Rückzug auf die manuelle Schreibmaschine kann man nicht darauf hoffen, dass man sich durch Ignoranz davonschleichen kann. Wir leben im 21. Jahrhundert, und man kann Unicode nicht durch vorsätzliche Ignoranz wegwünschen.

Sie müssen es lernen. Punkt. Es wird nie so einfach sein, dass "alles einfach funktioniert", denn das wird garantieren, dass eine Menge Dinge nicht was die Annahme entkräftet, dass es jemals einen Weg geben kann, "alles zum Laufen zu bringen".

Sie können vielleicht ein paar vernünftige Vorgaben für einige wenige und sehr begrenzte Vorgänge machen, aber nicht, ohne sehr viel mehr über die Dinge nachzudenken, als Sie es meiner Meinung nach getan haben.

Ein Beispiel dafür ist die kanonische Anordnung, die einige echte Kopfschmerzen verursachen wird. "\x{F5}" 'õ' , "o\x{303}" 'õ' , "o\x{303}\x{304}" '' y "o\x{304}\x{303}" '' sollten alle übereinstimmen 'õ' aber wie um alles in der Welt wollen Sie das tun? Das ist schwieriger, als es aussieht, aber es ist etwas, das Sie berücksichtigen müssen.

Wenn es eine Sache gibt, die ich über Perl weiß, dann ist es, was die Unicode-Bits tun und was nicht, und diese Sache verspreche ich Ihnen: " s U "

Man kann nicht einfach ein paar Standardeinstellungen ändern und schon läuft alles glatt. Es stimmt, dass ich mit PERL_UNICODE eingestellt auf "SA" aber das ist alles, und selbst das ist hauptsächlich für die Kommandozeile gedacht. Für die eigentliche Arbeit gehe ich all die vielen oben beschriebenen Schritte durch, und zwar sehr, ** sehr** sorgfältig.


¡dl do pu p u nl poo

63 Stimmen

Wie Sherm Pendley sagte: "Alle!". Wenn ich heute etwas Neues schreibe, sollte UTF-8 sein am einfachsten Art und Weise, Dinge zu erledigen. Das ist sie nicht. Ihr Textbaustein beweist es. Nicht jeder hat dieses Wissen, um so viele Zuhaltungen in die richtigen Positionen zu bringen. Es tut mir leid, ich hatte einen langen und anstrengenden Tag, deshalb werde ich morgen im Haupteintrag mehr mit Beispielen kommentieren.

13 Stimmen

@wk: Es ist also cool, dass ein Code wie perl -i.bak -pe 's/foo/bar' Pausen? Davon gibt es verdammt viel auf der Welt. Was für einen Vergleich wollen Sie für eq ? Ein UCA3-Vergleich? Hat lc es in UCA1 umwandeln? Wie können Sie das wissen? Wie werden Sie unvollständige und/oder nicht zusammenhängende Glyphen zuordnen? Ist es in Ordnung, dass der gesamte alte Code mit 8-Bit-Daten darin jetzt nicht mehr kompiliert werden kann? Ist es in Ordnung, dass Perl nicht mehr mit binären Daten arbeitet? Ist es in Ordnung, unterschiedliche Antworten zu erhalten? Ist es in Ordnung, zu diddeln a-z ohne deren Zustimmung aus dem Weg zu räumen? Ist es in Ordnung, Grapheme aufzubrechen? Ist eine 100-fache Verlangsamung beim Sortieren von Code akzeptabel? Was ist mit filesys?

1 Stimmen

@tchrist: warum sollte es einen alten Code kaputt machen, wenn wir die Verwendung von Unicode in neu Projekte? Vergessen wir mal Legacy-Code und Core Perl. Gibt es zum Beispiel einen Grund, UTF-8 in Moose-basierten Projekten zu vermeiden? Wenn nicht, denke ich, dass Moose die UTF-8-Unterstützung so weit wie möglich aktivieren könnte, da es Warnungen und strenge Pragma ermöglicht. Jetzt verschwenden wir nur noch Zeit, denn es gibt bereits eine Menge Code, der mit Moose geschrieben wurde und der möglicherweise kaputt geht ;)

101voto

jrockway Punkte 40754

Die Verarbeitung von Unicode-Text erfolgt in zwei Stufen. Die erste ist "wie kann ich ihn eingeben und ausgeben, ohne dass Informationen verloren gehen". Die zweite lautet: "Wie behandle ich den Text entsprechend den Konventionen der jeweiligen Sprache?

tchrist's Beitrag deckt beides ab, aber der zweite Teil ist es, aus dem 99% des Textes in seinem Beitrag stammen. Die meisten Programme handhaben E/A nicht einmal richtig, daher ist es wichtig, das zu verstehen, bevor man sich überhaupt Gedanken über Normalisierung und Kollationierung macht.

Dieser Beitrag zielt darauf ab, dieses erste Problem zu lösen

Wenn Sie Daten in Perl einlesen, ist es egal, in welcher Kodierung sie vorliegen. Es wird Speicher zugewiesen und die Bytes werden dort verstaut. Wenn Sie sagen print $str werden diese Bytes einfach an Ihr Terminal weitergegeben, das wahrscheinlich so eingestellt ist, dass es davon ausgeht, dass alles, was in das Terminal geschrieben wird, UTF-8 ist, und Ihr Text wird angezeigt.

Wunderbar.

Nur ist das nicht der Fall. Wenn Sie versuchen, die Daten als Text zu behandeln, werden Sie feststellen, dass etwas Schlimmes passiert. Sie brauchen nicht weiter zu gehen als length um zu sehen, dass das, was Perl über Ihre Zeichenkette denkt, und das, was Sie über Ihre Zeichenkette denken, nicht übereinstimmen. Schreiben Sie einen Einzeiler wie: perl -E 'while(<>){ chomp; say length }' und geben Sie ein und Sie erhalten 12... nicht die richtige Antwort, sondern 4.

Das liegt daran, dass Perl davon ausgeht, dass Ihre Zeichenkette kein Text ist. Sie müssen ihm sagen, dass es sich um Text handelt, bevor es Ihnen die richtige Antwort gibt.

Das ist ganz einfach; das Encode-Modul verfügt über die entsprechenden Funktionen. Der generische Einstiegspunkt ist Encode::decode (oder use Encode qw(decode) natürlich). Diese Funktion nimmt eine Zeichenkette aus der Außenwelt (wir nennen sie "Oktette", eine schicke Umschreibung für "8-Bit-Bytes") und wandelt sie in einen Text um, den Perl versteht. Das erste Argument ist ein Zeichencodierungsname, wie "UTF-8" oder "ASCII" oder "EUC-JP". Das zweite Argument ist die Zeichenkette. Der Rückgabewert ist ein Perl-Skalar, der den Text enthält.

(Außerdem gibt es Encode::decode_utf8 die UTF-8 als Kodierung voraussetzt).

Wenn wir unseren Einzeiler umformulieren:

perl -MEncode=decode -E 'while(<>){ chomp; say length decode("UTF-8", $_) }'

Wir tippen ein und erhalten "4" als Ergebnis. Erfolg.

Das ist die Lösung für 99% aller Unicode-Probleme in Perl.

Der Schlüssel ist, dass Sie jeden Text, der in Ihr Programm kommt, dekodieren müssen. Das Internet kann keine Zeichen übertragen. Dateien können keine Zeichen speichern. Es gibt keine Zeichen in Ihrer Datenbank. Es gibt nur Oktette, und Oktette können in Perl nicht als Zeichen behandelt werden. Sie müssen die kodierten Oktette mit dem Modul Encode in Perl-Zeichen dekodieren.

Die andere Hälfte des Problems besteht darin, Daten aus Ihrem Programm herauszuholen. Das ist einfach; Sie sagen einfach use Encode qw(encode) entscheiden Sie, in welcher Kodierung Ihre Daten vorliegen sollen (UTF-8 für Terminals, die UTF-8 verstehen, UTF-16 für Dateien unter Windows usw.), und geben Sie dann das Ergebnis von encode($encoding, $data) anstatt nur auszugeben $data .

Diese Operation wandelt die Zeichen von Perl, mit denen Ihr Programm arbeitet, in Oktette um, die von der Außenwelt verwendet werden können. Es wäre viel einfacher, wenn wir einfach Zeichen über das Internet oder an unsere Terminals senden könnten, aber das geht nicht: nur Oktette. Wir müssen also Zeichen in Oktette umwandeln, sonst sind die Ergebnisse undefiniert.

Zusammengefasst: alle Ausgänge kodieren und alle Eingänge dekodieren.

Wir werden nun über drei Probleme sprechen, die dies zu einer kleinen Herausforderung machen. Das erste sind die Bibliotheken. Verarbeiten sie Text richtig? Die Antwort ist: Sie versuchen es. Wenn Sie eine Webseite herunterladen, gibt Ihnen LWP das Ergebnis als Text zurück. Wenn Sie die richtige Methode für das Ergebnis aufrufen (und das ist zufällig decoded_content , nicht content der nur der Oktettstrom ist, den er vom Server erhalten hat). Datenbanktreiber können unzuverlässig sein; wenn Sie DBD::SQLite nur mit Perl verwenden, wird es funktionieren, aber wenn ein anderes Tool Text in einer anderen Kodierung als UTF-8 in Ihrer Datenbank gespeichert hat... nun... es wird nicht korrekt gehandhabt werden, bis Sie Code schreiben, um es korrekt zu behandeln.

Die Ausgabe von Daten ist in der Regel einfacher, aber wenn Sie "wide character in print" sehen, dann wissen Sie, dass Sie irgendwo die Kodierung durcheinander bringen. Diese Warnung bedeutet "Hey, du versuchst, Perl-Zeichen nach außen zu geben, und das macht keinen Sinn". Ihr Programm scheint zu funktionieren (weil die Gegenseite die rohen Perl-Zeichen normalerweise korrekt verarbeitet), aber es ist sehr fehlerhaft und könnte jeden Moment aufhören zu funktionieren. Reparieren Sie es mit einer expliziten Encode::encode !

Das zweite Problem ist UTF-8 kodierter Quellcode. Es sei denn, Sie sagen use utf8 am Anfang jeder Datei, wird Perl nicht davon ausgehen, dass Ihr Quellcode UTF-8 ist. Das bedeutet, dass jedes Mal, wenn Sie etwas sagen wie my $var = '' Wenn du das tust, fügst du Müll in dein Programm ein, der alles auf schreckliche Weise kaputt macht. Sie müssen nicht "utf8" verwenden, aber wenn Sie es nicht tun, werden Sie muss Verwenden Sie in Ihrem Programm keine Nicht-ASCII-Zeichen.

Das dritte Problem ist die Art und Weise, wie Perl mit The Past umgeht. Vor langer Zeit gab es so etwas wie Unicode noch nicht, und Perl nahm an, dass alles Latin-1-Text oder binär war. Wenn also Daten in Ihr Programm kommen und Sie beginnen, sie als Text zu behandeln, behandelt Perl jedes Oktett als ein Latin-1-Zeichen. Als wir nach der Länge von "" fragten, erhielten wir deshalb 12. Perl nahm an, dass wir mit der Latin-1-Zeichenkette "æååã" arbeiteten (die aus 12 Zeichen besteht, von denen einige nicht druckbar sind).

Dies wird als "implizites Upgrade" bezeichnet und ist eine durchaus sinnvolle Sache, aber nicht das, was Sie wollen, wenn Ihr Text nicht Latin-1 ist. Deshalb ist es wichtig, die Eingabe explizit zu dekodieren: Wenn Sie es nicht tun, wird Perl es tun, und es könnte es falsch machen.

Es gibt Probleme, wenn die Hälfte der Daten eine richtige Zeichenkette ist und ein anderer Teil noch binär ist. Perl wird den Teil, der noch binär ist, so interpretieren, als ob es sich um Latin-1-Text handelt, und ihn dann mit den richtigen Zeichendaten kombinieren. Das lässt es so aussehen, als ob die korrekte Behandlung der Zeichen Ihr Programm kaputt gemacht hätte, aber in Wirklichkeit haben Sie es einfach nicht genug repariert.

Hier ein Beispiel: Sie haben ein Programm, das eine UTF-8-kodierte Textdatei liest, und Sie fügen eine Unicode PILE OF POO in jede Zeile und drucken Sie sie aus. Sie schreiben es so:

while(<>){
    chomp;
    say "$_ ";
}

Und dann auf einige UTF-8 kodierte Daten, wie:

perl poo.pl input-data.txt

Es druckt die UTF-8-Daten mit einem poo am Ende jeder Zeile. Perfekt, mein Programm funktioniert!

Aber nein, Sie machen nur eine binäre Verkettung. Du liest Oktette aus der Datei, entfernst ein \n mit chomp, und dann das Anhängen der Bytes in der UTF-8-Darstellung der PILE OF POO Charakter. Wenn Sie Ihr Programm überarbeiten, um die Daten aus der Datei zu dekodieren und die Ausgabe zu kodieren, werden Sie feststellen, dass Sie Müll ("ð©") anstelle von poo erhalten. Das wird Sie zu der Annahme verleiten, dass das Dekodieren der Eingabedatei der falsche Weg ist. Ist es aber nicht.

Das Problem besteht darin, dass der Poo implizit als Latin-1 aufgewertet wird. Wenn Sie use utf8 um den wörtlichen Text anstelle des binären zu verwenden, dann wird es wieder funktionieren!

(Das ist das größte Problem, das ich sehe, wenn ich Leuten mit Unicode helfe. Sie haben einen Teil richtig gemacht, und das hat ihr Programm kaputt gemacht. Das ist das Traurige an undefinierten Ergebnissen: Sie können lange Zeit ein funktionierendes Programm haben, aber wenn Sie anfangen, es zu reparieren, geht es kaputt. Machen Sie sich keine Sorgen; wenn Sie Ihrem Programm Kodier-/Dekodieranweisungen hinzufügen und es bricht, bedeutet das nur, dass Sie noch mehr Arbeit vor sich haben. Das nächste Mal, wenn Sie von Anfang an mit Unicode planen, wird es viel einfacher sein).

Das ist eigentlich alles, was Sie über Perl und Unicode wissen müssen. Wenn Sie Perl sagen, was Ihre Daten sind, hat es die beste Unicode-Unterstützung unter allen gängigen Programmiersprachen. Wenn Sie jedoch davon ausgehen, dass Perl auf magische Weise weiß, welche Art von Text Sie ihm geben, dann werden Sie Ihre Daten unwiderruflich zerstören. Nur weil Ihr Programm heute auf Ihrem UTF-8-Terminal funktioniert, heißt das noch lange nicht, dass es morgen mit einer UTF-16-kodierten Datei funktionieren wird. Gehen Sie also jetzt auf Nummer sicher und ersparen Sie sich das Kopfzerbrechen, die Daten Ihrer Benutzer zu zerstören!

Der einfache Teil der Handhabung von Unicode ist die Kodierung der Ausgabe und die Dekodierung der Eingabe. Der schwierige Teil besteht darin, alle Eingaben und Ausgaben zu finden und zu bestimmen, welche Kodierung sie haben. Aber dafür bekommt man ja auch das große Geld :)

2 Stimmen

Das Prinzip wird gut erklärt, aber es fehlt der praktische Ansatz für E/A. Die explizite Verwendung des Encode Modul ist mühsam und fehleranfällig, und es macht das Lesen des Codes bezüglich der E/A wirklich mühsam. E/A-Schichten bieten eine Lösung, da sie transparent kodieren und dekodieren, wo dies erforderlich ist. open y binmode erlauben ihre Angabe, und pragma open setzt die Standardwerte, wie tchrist in seiner Antwort empfiehlt.

50voto

Randy Stauner Punkte 696

Wir sind uns alle einig, dass dies aus vielen Gründen ein schwieriges Problem ist, aber genau das ist der Grund, warum wir versuchen sollten, es für alle leichter zu machen.

Es gibt ein neues Modul auf CPAN, utf8::all die versucht, "Unicode einzuschalten. Alles davon".

Wie bereits erwähnt, kann man nicht auf magische Weise das gesamte System (externe Programme, externe Webanfragen usw.) dazu bringen, ebenfalls Unicode zu verwenden, aber wir können zusammenarbeiten, um vernünftige Werkzeuge zu entwickeln, die die Lösung allgemeiner Probleme erleichtern. Das ist der Grund, warum wir Programmierer sind.

Wenn utf8::all etwas nicht tut, was es Ihrer Meinung nach tun sollte, dann lassen Sie es uns verbessern, damit es besser wird. Oder lasst uns zusätzliche Werkzeuge entwickeln, die zusammen die unterschiedlichen Bedürfnisse der Menschen so gut wie möglich erfüllen können.

`

5 Stimmen

Ich sehe eine Menge Raum für Verbesserungen in der zitierten utf8::all Modul. Es wurde geschrieben, bevor die unicode_strings Funktion, die F L Ls Regexe so festlegt, dass sie eine /u über sie. Ich bin nicht davon überzeugt, dass es eine Ausnahme bei Codierungsfehlern auslöst, und das ist etwas, das Sie wirklich haben müssen. Es lädt nicht in der use charnames ":full" pragma, das noch nicht automatisch geladen ist. Es warnt nicht bei [a-z] und so weiter, printf Stringbreiten, unter Verwendung von \n 代わりに \R y . 代わりに \X aber vielleicht sind diese eher ein Perl::Critic Materie. Wenn ich es wäre, würde ich ein- und aussteigen.

13 Stimmen

@tchrist Der Issue Tracker für utf8::all ist hier. github.com/doherty/utf8-all/issues Sie würden sich über Ihre Vorschläge freuen.

4 Stimmen

@Schwern: s, aber Sie können gerne von dem, was ich hier geschrieben habe, klauen und klauen. Um ehrlich zu sein, bin ich immer noch das Gefühl / lernen, was getan werden kann vs. was getan werden sollte, und wo. Hier ist ein schönes Beispiel für die Auslagerung der Sortierung: unichars -gs '/(?=\P{Ll})\p{Lower}|(?=\P{Lu})\p{Upper}/x' | ucsort --upper | cat -n | less -r . In ähnlicher Weise werden kleine Vorverarbeitungsschritte wie ... | ucsort --upper --preprocess='s/(\d+)/sprintf "%#012d", $1/ge' kann auch sehr nett sein, und ich möchte nicht die Entscheidungen anderer für sie treffen. Ich bin immer noch meine Unicode-Toolbox aufbauen .

39voto

brian d foy Punkte 124323

Ich glaube, Sie missverstehen Unicode und seine Beziehung zu Perl. Egal, wie Sie Daten speichern, Unicode, ISO-8859-1 oder viele andere Dinge, muss Ihr Programm wissen, wie es die Bytes, die es als Eingabe erhält, interpretieren (Dekodierung) und wie es die Informationen, die es ausgeben will, darstellen soll (Kodierung). Wenn Sie diese Interpretation falsch vornehmen, verstümmeln Sie die Daten. Es gibt keine magische Standardeinstellung in Ihrem Programm, die den Dingen außerhalb Ihres Programms sagt, wie sie sich verhalten sollen.

Sie denken wahrscheinlich, dass es schwer ist, weil Sie daran gewöhnt sind, dass alles in ASCII geschrieben wird. Alles, woran Sie hätten denken sollen, wurde von der Programmiersprache und all den Dingen, mit denen sie interagieren musste, einfach ignoriert. Wenn alles nur UTF-8 verwenden würde und Sie keine Wahl hätten, dann wäre UTF-8 genauso einfach. Aber nicht alles verwendet UTF-8. Sie wollen zum Beispiel nicht, dass Ihr Eingabe-Handle denkt, dass es UTF-8 Oktette bekommt, wenn es das nicht tatsächlich tut, und Sie wollen nicht, dass Ihre Ausgabe-Handles UTF-8 sind, wenn das Ding, das von ihnen liest, nicht mit UTF-8 umgehen kann. Perl hat keine Möglichkeit, diese Dinge zu wissen. Deshalb sind Sie der Programmierer.

Ich denke nicht, dass Unicode in Perl 5 zu kompliziert ist. Ich denke, es ist beängstigend und die Leute meiden es. Das ist ein Unterschied. Zu diesem Zweck habe ich Unicode in Perl lernen, 6. Auflage und es gibt eine Menge Unicode-Zeug in Effektive Perl-Programmierung . Sie müssen die Zeit aufwenden, um Unicode zu lernen und zu verstehen, wie es funktioniert. Andernfalls werden Sie es nicht effektiv nutzen können.

3 Stimmen

Ich denke, Sie haben Recht: Es ist beängstigend. Sollte es das sein? Für mich ist Unicode ein Segen, es in Perl5 zu benutzen ist es nicht (ich gehe nicht davon aus, dass irgendetwas ASCII ist, meine Muttersprache braucht mindestens iso8859-4). Ich habe Rakudo installiert und alles, was ich mit UTF-8 (in dieser begrenzten Sandbox) ausprobiert habe, hat sofort funktioniert. Habe ich etwas übersehen? Ich betone es noch einmal: es ist gut, eine fein abgestimmte Unicode-Unterstützung zu haben, aber in den meisten Fällen ist das nicht nötig. Um die Angst vor dem Thema zu nehmen, ist eine Möglichkeit, dass jeder eine Menge liest, um die Interna zu verstehen. Anderes: wir haben spezielle pragma, also use utf8_everywhere macht die Menschen glücklich. Warum nicht auch der letzte?

3 Stimmen

Ich glaube immer noch, dass Sie das Thema verfehlen. Was hat funktioniert? Man muss die Interna nicht verstehen. Sie müssen verstehen Externe und wie Sie mit Zeichenketten umgehen wollen, die unterschiedliche Kodierungen und unterschiedliche Darstellungen der gleichen Zeichen haben. Lesen Sie Toms Ratschläge noch einmal. Das meiste von dem, was er sagt, wirst du in Rakudo sicher nicht wiederfinden.

0 Stimmen

Vielleicht haben Sie Recht und ich verstehe den Punkt nicht, ich will nicht streiten. [Aber Randy Stauner hat in seiner Antwort auf ein neues Modul hingewiesen utf::all . Ist an einem solchen Modul etwas falsch? Sollten wir es (oder etwas Ähnliches) nicht im Kern von Perl haben? Aus meiner Sicht macht es die Verwendung von UTF-8 so viel einfacher und den Code sauberer. Überhaupt keine Angst.

29voto

MeirG Punkte 291

Wenn ich diesen Thread lese, habe ich oft den Eindruck, dass die Leute den Begriff " UTF-8 " als Synonym für " Unicode ". Bitte unterscheiden Sie zwischen den "Code-Points" von Unicode, die eine vergrößerte Variante des ASCII-Codes sind, und den verschiedenen "Kodierungen" von Unicode. Und davon gibt es einige, unter anderem UTF-8, UTF-16 y UTF-32 sind die aktuellen und einige weitere sind veraltet.

Bitte, UTF-8 (wie auch alle anderen Kodierungen ) existieren und nur bei der Eingabe oder der Ausgabe eine Bedeutung haben. Intern, seit Perl 5.8.1, werden alle Strings als Unicode "Code-Points" gehalten. Es stimmt, dass Sie einige Funktionen aktivieren müssen, wie zuvor bewundernd beschrieben.

20 Stimmen

Ich stimme zu, dass die Leute zu oft U mit UTF-81632 verwechseln, aber es ist grundlegend und kritisch nicht wahr dass U nur ein erweiterter Zeichensatz relativ zu s ist. Bestenfalls ist das nicht mehr als bloße s10646 . U enthält viel mehr : Regeln für Kollationierung, Groß- und Kleinschreibung, Normalisierungsformen, Graphem-Cluster, Wort- und Zeilenumbruch, Skripte, numerische Äquivs, Breiten, Bidirektionalität, Glyphenvarianten, kontextabhängiges Verhalten, Gebietsschemata, Regexe, Kombinationsklassen, 100 Eigenschaften und vieles mehr

15 Stimmen

@tchrist: der erste schritt besteht darin, die daten in ihr programm und nach außen zu bekommen, ohne sie zu zerstören. dann können sie sich um kollation, groß- und kleinschreibung, glyphenvarianten usw. kümmern. kleine schritte.

7 Stimmen

Ich stimme zu, dass es oberste Priorität sein muss, Perl dazu zu bringen, die Ein- oder Ausgabe nicht zu zerstören. Was ich gerne hätte, wäre ein Modul oder Pragma, das die folgende fiktive Konversation verkörpern könnte: "- Liebes Perl. Für dieses Programm werden alle Eingaben und Ausgaben ausschließlich in UTF-8 erfolgen. Könntest du bitte meine Daten nicht zerstören? - Also nur UFT-8 sagen Sie. Bist du dir da sicher? - Ja. - Wirklich, wirklich sicher? - Ganz sicher. - Und Sie akzeptieren, dass ich mich seltsam verhalte, wenn man mir Nicht-UTF-8-Daten vorsetzt? - Ja, gut. - Also gut."

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X