556 votes

Pourquoi Perl moderne n’évite pas de UTF-8 par défaut ?

Je me demande pourquoi la plupart des solutions modernes construits à l'aide de Perl n'activez pas l'UTF-8 par défaut.

Je comprends qu'il ya beaucoup de l'héritage des problèmes de base des scripts Perl, où il peut casser des choses. Mais, de mon point de vue, dans la 21st century, gros de nouveaux projets (ou de projets avec un grand point de vue) devraient faire leur logiciel UTF-8 la preuve à partir de zéro. Je ne vois pas qu'il se passe. Par exemple, l'Orignal permet stricte et des avertissements, mais pas Unicode. Moderne::Perl réduit trop passe-partout, mais pas de l'UTF-8 de la manipulation.

Pourquoi? Y at-il des raisons à éviter UTF-8 dans moderne Perl projets de l'année 2011?


Commentaires @tchrist ai trop longtemps, je suis donc de l'ajouter ici.

Il semble que je n'ai pas à me faire comprendre. Laissez-moi ajouter certaines choses.

tchrist et je vois situation assez similaire, mais nos conclusions sont complètement opposées. Je suis d'accord, la situation avec l'Unicode est compliqué, mais c'est pourquoi nous (utilisateurs de Perl et des codeurs) besoin d'un calque (ou pragma) qui fait de l'UTF-8 manipulation facile, comme elle doit l'être aujourd'hui.

tchrist de relever de nombreux aspects à couvrir, je vais la lire et y réfléchir pendant des jours ou même des semaines. Encore, ce n'est pas mon point. tchrist tente de prouver qu'il n'y a pas un seul chemin "afin de permettre à l'UTF-8". Je n'ai pas autant de connaissances pour argumenter avec ça. Donc, je m'en tiens à des exemples vivants.

J'ai joué un peu avec Rakudo et UTF-8 était là, tout simplement parce que j'avais besoin. Je n'ai pas de problèmes, juste que cela fonctionne. Peut-être il ya une limite quelque part plus loin, mais au début, j'ai testé fonctionné comme je l'espérais.

Ne pourrait-il pas être un but en moderne Perl 5 trop? Je stress de plus: je ne suggère pas de l'UTF-8 comme jeu de caractères par défaut pour la base de Perl, je suggère la possibilité de déclencher elle avec un clin d'œil pour ceux qui développent de nouveaux projets.

Un autre exemple, mais avec un ton négatif. Les cadres en faciliter le développement. Il y a quelques années, j'ai essayé de frameworks web, mais juste jeté loin parce que "activation de l'UTF-8" était si obscur. Je n'ai pas trouver comment et où le crochet de support de l'Unicode. Il était tellement de temps que je l'ai trouvé plus facile pour aller à l'ancienne. Maintenant que j'ai vu ici il y a une prime à traiter le même problème avec Mason 2: Comment faire Mason2 utf8 propre? Donc, c'est joli cadre nouveau, mais de l'utiliser avec de l'UTF-8 a besoin d'une profonde connaissance de son fonctionnement interne. C'est comme un grand panneau rouge: STOP, n'utilisez pas de moi!

J'aime vraiment Perl. Mais traiter avec l'Unicode est douloureux. Encore je me trouve en cours d'exécution contre les murs. D'une certaine façon tchrist est droit et des réponses à mes questions: de nouveaux projets, n'attirent pas l'UTF-8, car il est trop compliqué de Perl 5.

1145voto

tchrist Points 47116
<hr> <h1> </h1>

96voto

jrockway Points 23734

Il y a deux étapes de traitement de texte Unicode. La première est "comment puis-je d'entrée et de sortie sans perte d'information". La deuxième "comment dois-je traiter le texte, selon les conventions de la langue". tchrist post couvre à la fois, mais la deuxième partie est, où 99% de la le texte dans son poste. La plupart des programmes ne sont pas à même de gérer des e / s correctement, il est donc important de comprendre que, avant même de commencer à vous soucier de la normalisation et de classement.

Ce post a pour objectif de résoudre ce premier problème

Lorsque vous lisez des données en Perl, il ne se soucie pas de l'encodage que c'est. Il alloue de la mémoire et de caches les octets loin de là. Si vous dites print $str, c'est juste blits ces octets à votre terminal, qui est probablement à assumer tout ce qui est écrit, c'est de l'UTF-8, et votre texte s'affiche.

Merveilleux.

Sauf, qu'il ne l'est pas. Si vous essayez de traiter les données sous forme de texte, vous verrez que quelque Chose de Mauvais se passe. Vous avez besoin de ne pas aller plus loin que length pour voir que ce que Perl pense au sujet de votre chaîne et de ce que vous en pensez à propos de votre chaîne de désaccord. Écrire un one-liner comme: perl -E 'while(<>){ chomp say length }' et le type en 文字化け et vous obtenez 12... pas la réponse correcte, 4.

C'est parce que Perl suppose que votre chaîne n'est pas du texte. Vous avez à dire il que c'est le texte avant de vous donner la bonne réponse.

C'est assez facile, l'encodage module a pour fonctions de faire. Le générique d'un point d'entrée Encode::decode (ou use Encode qw(decode), bien sûr). Cette fonction prend une chaîne de caractères à partir de la monde extérieur (ce que nous appellerons les "octets", une fantaisie de la façon de le dire "Octets de 8 bits"), et il se transforme en texte que Perl se comprendre. Le premier argument est un codage de caractères nom, comme "UTF-8" ou "ASCII" ou "EUC-JP". Le deuxième argument est la chaîne de caractères. Le retour la valeur est le Perl scalaire contenant le texte.

(Il est également Encode::decode_utf8, ce qui suppose que l'UTF-8 pour l' encodage).

Si nous réécrire notre one-liner:

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

nous tapez dans 文字化け et obtenir "4" comme résultat. Succès.

Que, là, c'est la solution à 99% de l'Unicode des problèmes en Perl.

La clé est, chaque fois qu'un texte vient dans votre programme, vous devez décoder c'. L'Internet ne peut pas transmettre des caractères. Les fichiers ne peuvent pas stocker de des personnages. Il n'y a pas de caractères dans votre base de données. Il y a seulement octets, et vous ne pouvez pas traiter les octets comme des caractères en Perl. Vous devez décoder les octets codés en Perl caractères avec l'encodage du module.

L'autre moitié du problème est d'obtenir des données de votre programme. C'est facile; il suffit de dire use Encode qw(encode), décider de ce que les l'encodage de vos données en UTF-8 pour les terminaux comprendre UTF-8, UTF-16 pour les fichiers de Windows, etc.), et puis la sortie de la suite d' encode( $encoding, $data ) au lieu de simplement la sortie d' $data.

Cette opération convertit en Perl caractères, qui est ce que votre programme fonctionne d'octets qui peut être utilisé par le monde extérieur. Il serait beaucoup plus facile si nous pouvions simplement envoyer des caractères au cours de la Internet ou à nos terminaux, mais nous ne pouvons pas: octets seulement. Nous avons donc pour convertir les caractères d'octets, sinon les Résultats ne Sont pas définis.

Pour résumer: encoder toutes les sorties, les décoder toutes les entrées.

Maintenant, nous allons parler de trois aspects qui font de ce un peu difficile. La première est de bibliothèques. Gèrent-ils le texte correctement? La réponse c'est... ils essaient. Si vous téléchargez une page web, LWP vous donnera votre résultat sous forme de texte. Si vous appelez la méthode sur le résultat, que est (et qui se trouve être decoded_content, pas content, ce qui est juste le flux d'octets qu'il a obtenu à partir du serveur.) Pilotes de base de données peut être feuilletée; si vous utilisez DBD::SQLite avec juste Perl, cela fonctionnera, mais si un autre outil a mis le texte stocké comme certains l'encodage autre que UTF-8 dans votre base de données... et bien... elle ne va pas être traitées correctement jusqu'à ce que vous écrivez du code pour les manipuler correctement.

La sortie de données est généralement plus facile, mais si vous voyez des caractères larges dans print", alors vous savez que vous avez raté l'encodage quelque part. Que avertissement signifie "hey, vous êtes en essayant de fuite de Perl caractères monde extérieur et qui n'a pas de sens". Votre programme s'affiche de travailler (parce que l'autre extrémité gère habituellement les premières Perl caractères correctement), mais c'est très approximatif et pourrait cesser de fonctionner à tout moment. Fixer avec un explicite Encode::encode!

Le deuxième problème est codé en UTF-8 du code source. À moins que vous dire use utf8 en haut de chaque fichier, Perl ne supposons pas que votre source le code est UTF-8. Cela signifie que chaque fois que vous dites quelque chose comme my $var = 'ほげ', vous êtes l'injection de déchets dans votre programme totalement tout casser horriblement. Vous n'avez pas à "utiliser utf8", mais si vous ne le faites pas, vous devez pas utiliser les caractères non-ASCII dans votre programme.

Le troisième problème est la façon dont Perl gère Le Passé. Il y A longtemps, il n'y a pas une telle chose comme de l'Unicode, et perl suppose que tout est le Latin-1 texte ou binaire. Ainsi, lorsque les données arrivent dans votre programme et vous commencer le traitement de texte, Perl traite chaque octet comme un Latin-1 caractère. C'est pourquoi, lorsque nous avons demandé à la longueur de "文字化け", nous 12. Perl supposé que nous étions sur le Latin-1 chaîne "æååã" (qui est de 12 caractères, certaines sont non-impression).

Ceci est appelé un "implicite de mise à niveau", et c'est parfaitement raisonnable chose à faire, mais ce n'est pas ce que vous voulez si votre texte n'est pas Latin-1. C'est pourquoi il est essentiel explicitement décoder entrée: si vous ne le faites pas c', Perl va, et ça risque de faire mal.

Les personnes en difficulté, où la moitié de leurs données est un bon personnage chaîne, et une partie est toujours binaire. Perl va interpréter la partie qui est encore binaires comme si il est en Latin-1 texte, puis les combiner avec les caractère correct des données. Cela permettra de la faire ressembler à de la manipulation de votre les caractères correctement cassé votre programme, mais dans la réalité, vous venez de n'est pas assez.

Voici un exemple: vous avez un programme qui lit une codé en UTF-8 de texte fichier, vous virer de bord sur Unicode PILE OF POO à chaque ligne, et que vous imprimez c'. Vous l'écrire comme:

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

48voto

Randy Stauner Points 541

Nous sommes tous d'accord que c'est un problème difficile pour de nombreuses raisons, mais c'est précisément la raison pour essayer de le rendre plus facile pour tout le monde.

Il y a un récent module CPAN: utf8::tous que les tentatives de "tourner sur Unicode. Tout cela".

Comme cela a été souligné, vous ne pouvez pas magiquement faire de l'ensemble du système (en dehors des programmes, des requêtes web externes, etc) utiliser l'Unicode, mais nous pouvons travailler ensemble pour rendre sensible des outils qui permettent de faire des problèmes communs plus facile. C'est la raison pour laquelle nous sommes des programmeurs.

Si utf8::ne pas faire quelque chose que vous pensez qu'il devrait, nous allons l'améliorer pour le rendre meilleur. Ou nous allons faire d'autres outils qui, ensemble, peuvent convenir à des personnes de différents besoins aussi bien que possible.

35voto

brian d foy Points 71781

Je pense que vous ne comprenez pas l'Unicode et de sa relation à Perl. Peu importe la façon dont vous stockez des données, Unicode, ISO-8859-1, ou bien d'autres choses, votre programme doit savoir comment interpréter les octets qu'il reçoit en entrée (décodage) et la façon de représenter l'information qu'il veut de sortie (encodage). Obtenir que l'interprétation du mal et de vous corrompre les données. Il n'y a pas un peu de magie de configuration par défaut, à l'intérieur de votre programme qui va dire les choses en dehors de votre programme de la façon d'agir.

Vous pensez que c'est dur, le plus probable, parce que vous êtes habitué à tout ce qui se ASCII. Tout ce que vous avez réfléchi à ce sujet a été tout simplement ignorés par le langage de programmation et toutes les choses qu'il avait à interagir avec. Si tout ce qui sert à rien, mais UTF-8 et que vous n'avait pas le choix, alors UTF-8 serait tout aussi facile. Mais non, tout n'utiliser l'UTF-8. Par exemple, vous ne voulez pas que votre entrée poignée de penser que c'est de l'UTF-8 octets à moins qu'il ne l'est réellement, et vous ne voulez pas que votre sortie poignées pour être en UTF-8 si la chose leur lecture peut gérer l'UTF-8. Perl n'a aucun moyen de savoir ces choses. C'est pourquoi vous êtes le programmeur.

Je ne pense pas que Unicode en Perl 5 est trop compliqué. Je pense que c'est effrayant et les gens à éviter. Il y a une différence. À cette fin, j'ai mis en Unicode dans l'Apprentissage du langage Perl, 6e Édition, et il y a beaucoup de l'Unicode des trucs Efficaces de Programmation Perl. Vous avez à consacrer du temps pour apprendre et comprendre Unicode et comment il fonctionne. Vous n'allez pas être en mesure de l'utiliser efficacement le contraire.

28voto

MeirG Points 161

Lors de la lecture de ce fil, j'ai souvent l'impression que les gens sont à l'aide de "UTF-8" comme synonyme de "Unicode". Merci de faire une distinction entre Unicode "Code-Points" qui sont une hypertrophie de la famille du code ASCII et Unicode divers "encodages". Et il y en a quelques-uns d'entre eux, dont l'UTF-8, UTF-16 et UTF-32 sont celles en vigueur actuellement et quelques autres sont obsolètes.

S'il vous plaît, UTF-8 (ainsi que tous les autres encodages) existe et n'ont de sens en entrée ou en sortie. En interne, depuis Perl 5.8.1, toutes les chaînes sont conservées sous la forme Unicode "Code-points". Vrai, vous avez pour activer certaines fonctionnalités avec admiration, comme couvertes ci-dessus.

Meir

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X