Perché il moderno Perl evita UTF-8 di default?


557

Mi chiedo perché la maggior parte delle soluzioni moderne realizzate con Perl non abiliti UTF-8 per impostazione predefinita.

Capisco che ci sono molti problemi legacy per gli script Perl di base, in cui potrebbe rompere le cose. Ma, dal mio punto di vista, nel 21 ° secolo, i grandi nuovi progetti (o progetti con un grande punto di vista) dovrebbero fare il loro software UTF-8 a prova da zero. Ancora non lo vedo accadere. Ad esempio, Moose abilita rigidi e avvisi, ma non Unicode . Moderno :: Perl riduce anche la piastra della caldaia, ma non la gestione UTF-8.

Perché? Ci sono alcuni motivi per evitare UTF-8 nei moderni progetti Perl nel 2011?


Commentare @tchrist è troppo lungo, quindi lo aggiungo qui.

Sembra che non mi sia chiarito. Vorrei provare ad aggiungere alcune cose.

Tchrist e io vediamo la situazione in modo abbastanza simile, ma le nostre conclusioni sono completamente a estremità opposte. Sono d'accordo, la situazione con Unicode è complicata, ma questo è il motivo per cui noi (utenti e programmatori Perl) abbiamo bisogno di un livello (o pragma) che renda la gestione UTF-8 facile come deve essere al giorno d'oggi.

Tchrist ha sottolineato molti aspetti da trattare , leggerò e penserò a loro per giorni o addirittura settimane. Tuttavia, questo non è il mio punto. tchrist prova a dimostrare che non esiste un solo modo "per abilitare UTF-8". Non ho molta conoscenza per discuterne. Quindi, mi attengo agli esempi dal vivo.

Ho giocato con Rakudo e UTF-8 era proprio lì di cui avevo bisogno . Non ho avuto problemi, ha funzionato. Forse ci sono alcune limitazioni da qualche parte più in profondità, ma all'inizio tutto ciò che ho testato ha funzionato come mi aspettavo.

Non dovrebbe essere un obiettivo anche nel moderno Perl 5? Lo sottolineo di più: non sto suggerendo UTF-8 come set di caratteri predefinito per il core Perl, suggerisco la possibilità di attivarlo in un attimo per coloro che sviluppano nuovi progetti.

Un altro esempio, ma con un tono più negativo. I frame dovrebbero facilitare lo sviluppo. Alcuni anni fa, ho provato i framework web, ma li ho semplicemente buttati via perché "abilitare UTF-8" era così oscuro. Non ho trovato come e dove agganciare il supporto Unicode. È stato così tanto tempo che ho trovato più facile andare alla vecchia maniera. Ora ho visto che c'era una taglia per affrontare lo stesso problema con Mason 2: come rendere pulito Mason2 UTF-8? . Quindi, è un framework piuttosto nuovo, ma usarlo con UTF-8 richiede una profonda conoscenza dei suoi interni. È come un grande cartello rosso: STOP, non usarmi!

Mi piace molto Perl. Ma trattare con Unicode è doloroso. Mi trovo ancora a correre contro i muri. In qualche modo tchrist ha ragione e risponde alle mie domande: i nuovi progetti non attraggono UTF-8 perché è troppo complicato in Perl 5.


15
Mi dispiace ma sono d'accordo con @tchrist - UTF-8 è estremamente difficile. Non esiste un framework o uno strumento che "gira uno switch" e lo gestisce correttamente. È qualcosa a cui devi pensare direttamente durante la progettazione della tua applicazione, non qualcosa che qualsiasi tipo di framework o linguaggio può gestire per te. Se per caso rakudo ha funzionato per te, non sei stato abbastanza avventuroso con i tuoi casi di test, dato che prenderanno diversi esempi nella risposta di @ tchrist e nel macellaio.
Billy ONeal

12
Cosa speri esattamente Moose o Modern :: Perl? Trasformare magicamente i dati dei caratteri codificati casualmente in file e database in dati validi di nuovo?
jrockway,

13
Cosa significa? Moose non ha nulla a che fare con la manipolazione del testo. Perché dovrebbe conoscere la codifica dei caratteri, e tanto meno sceglierne uno predefinito per te? (Comunque, il motivo per cui i pragmi che elenchi non toccano la codifica è perché la convenzione prevede che i pragmi Perl influenzino il comportamento lessicale . Supponendo che l'intero mondo, altri moduli inclusi, sia UTF-8 è semplicemente la cosa sbagliata da fare Questo non è PHP o Ruby qui.)
jrockway,

8
(Inoltre ... "la maggior parte delle moderne app Perl" si interrompe su UTF-8? Non ho mai scritto un'applicazione, Perl o altro, che non sia Unicode-clean.)
jrockway

11
Nb. tchrist (Tom Christiansen) ha pubblicato il suo [ training.perl.com/OSCON2011/index.html i materiali di Tom Christiansen per OSCON 2011] su Unicode. Quello intitolato "Unicode Support Shootout: The Good, The Bad, e the (principalmente) Ugly" parla del supporto Unicode in diversi linguaggi di programmazione. Solo Google Go e Perl5 hanno il supporto per Unicode completo, solo Google Go integrato (nessuna menzione di Perl6).
Jakub Narębski,

Risposte:


1146

𝙎𝙞𝙢𝙥𝙡𝙚𝙨𝙩 : 𝟕 𝘿𝙞𝙨𝙘𝙧𝙚𝙩𝙚 𝙍𝙚𝙘𝙤𝙢𝙢𝙚𝙣𝙙𝙖𝙩𝙞𝙤𝙣𝙨

  1. Imposta l' PERL_UNICODEinvariabile su AS. Questo fa decodificare tutti gli script Perl @ARGVcome stringhe UTF ‑ 8 e imposta la codifica di tutti e tre gli stdin, stdout e stderr su UTF ‑ 8. Entrambi sono effetti globali, non lessicali.

  2. Nella parte superiore del file sorgente (programma, modulo, libreria, dohickey), affermare in modo evidente che si sta eseguendo perl versione 5.12 o migliore tramite:

    use v5.12;  # minimal for unicode string feature
    use v5.14;  # optimal for unicode string feature
  3. Abilita avvisi, poiché la dichiarazione precedente abilita solo le restrizioni e le caratteristiche, non gli avvisi. Suggerisco anche di promuovere gli avvisi Unicode in eccezioni, quindi usa entrambe queste righe, non solo una. Si noti tuttavia che in v5.14, la utf8classe di avviso comprende tre altri subwarning che possono essere abilitati separatamente:nonchar , surrogate, e non_unicode. Questi su cui potresti voler esercitare un maggiore controllo.

    use warnings;
    use warnings qw( FATAL utf8 );
  4. Dichiara che questa unità sorgente è codificata come UTF ‑ 8. Sebbene un tempo questo pragma facesse altre cose, ora serve solo questo scopo singolare e nessun altro:

    use utf8;
  5. Dichiara che tutto ciò che apre un filehandle all'interno di questo ambito lessicale ma non altrove presuppone che quel flusso sia codificato in UTF ‑ 8, a meno che non lo dica diversamente. In questo modo non influisci sul codice di altri moduli o di altri programmi.

    use open qw( :encoding(UTF-8) :std );
  6. Abilita i caratteri nominati tramite \N{CHARNAME}.

    use charnames qw( :full :short );
  7. Se hai un DATAhandle, devi impostare esplicitamente la sua codifica. Se vuoi che sia UTF ‑ 8, allora dì:

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

Ovviamente non c'è fine ad altre questioni di cui potresti eventualmente trovarti preoccupato, ma queste basteranno ad approssimare l'obiettivo statale di "far funzionare tutto con UTF-8", anche se per un senso un po 'indebolito di quei termini.

Un altro pragma, sebbene non sia correlato a Unicode, è:

      use autodie;

È fortemente raccomandato.

🌴 🐪🐫🐪 🌞 𝕲𝖔 𝕿𝖍𝖔𝖚 𝖆𝖓𝖉 𝕯𝖔 𝕷𝖎𝖐𝖊𝖜𝖎𝖘𝖊 🌞 🐪🐫🐪 🐁


🎁 🐪 𝕭𝖔𝖎𝖑𝖊𝖗⸗𝖕𝖑𝖆𝖙𝖊 𝖋𝖔𝖗 𝖀𝖓𝖎𝖈𝖔𝖉𝖊⸗𝕬𝖜𝖆𝖗𝖊 𝕮𝖔𝖉𝖊 🐪 🎁


La mia caldaia in questi giorni tende ad apparire così:

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__

🎅 𝕹 𝖔 𝕸 𝖆 𝖌 𝖎 𝖈 𝕭 𝖚 𝖑 𝖑 𝖊 𝖙 🎅


Dicendo che “Perl dovrebbe [in qualche modo! ] abilita Unicode per impostazione predefinita "non inizia nemmeno a pensare di andare in giro a dire abbastanza per essere anche marginalmente utile in una sorta di caso raro e isolato. Unicode è molto più di un semplice repertorio di personaggi; è anche il modo in cui tutti questi personaggi interagiscono in molti, molti modi.

Anche le semplici misure minime che (alcune) persone sembrano pensare di volere sono garantite per spezzare miseramente milioni di righe di codice, codice che non ha alcuna possibilità di "aggiornarsi" al tuo nuovo spavaldo Brave New World modernità .

È molto più complicato di quanto la gente pretenda. Ci ho pensato moltissimo, negli ultimi anni. Mi piacerebbe essere dimostrato che mi sbaglio. Ma non credo di esserlo. Unicode è fondamentalmente più complesso del modello che vorresti imporgli, e qui c'è complessità che non puoi mai spazzare sotto il tappeto. Se ci provi, infrangerai il tuo codice o quello di qualcun altro. Ad un certo punto, devi semplicemente scomporre e scoprire di cosa tratta Unicode. Non puoi fingere che sia qualcosa che non lo è.

🐪 fa di tutto per rendere Unicode semplice, molto più di ogni altra cosa che abbia mai usato. Se ritieni che ciò sia negativo, prova qualcos'altro per un po '. Quindi torna a 🐪: o sarai tornato in un mondo migliore, oppure porterai la conoscenza dello stesso con te in modo che possiamo usare la tua nuova conoscenza per rendere 🐪 migliore in queste cose.


💡 𝕴𝖉𝖊𝖆𝖘 𝖋𝖔𝖗 𝖆 𝖀𝖓𝖎𝖈𝖔𝖉𝖊 ⸗ 𝕬𝖜𝖆𝖗𝖊 🐪 𝕷𝖆𝖚𝖓𝖉𝖗𝖞 𝕷𝖎𝖘𝖙 💡


Come minimo, ecco alcune cose che sembrerebbero necessarie per 🐪 per “abilitare Unicode di default”, come dici tu:

  1. Tutto 🐪 il codice sorgente dovrebbe essere in UTF-8 per impostazione predefinita. Puoi ottenerlo con use utf8o export PERL5OPTS=-Mutf8.

  2. La DATAmaniglia 🐪 dovrebbe essere UTF-8. Dovrai farlo in base al pacchetto, come in binmode(DATA, ":encoding(UTF-8)").

  3. Gli argomenti del programma su script 🐪 dovrebbero essere intesi come UTF-8 per impostazione predefinita. export PERL_UNICODE=A, o perl -CA, o export PERL5OPTS=-CA.

  4. I flussi di input, output ed errore standard devono essere predefiniti su UTF-8. export PERL_UNICODE=Sper tutti loro, o I, Oe / o Esolo per alcuni di essi. Questo è come perl -CS.

  5. Eventuali altri handle aperti da 🐪 devono essere considerati UTF-8 se non diversamente indicato; export PERL_UNICODE=Do con ie oper quelli particolari; export PERL5OPTS=-CDfunzionerebbe. Questo li rende -CSADtutti.

  6. Copri entrambe le basi più tutti i flussi con cui apri export PERL5OPTS=-Mopen=:utf8,:std. Vedi uniquote .

  7. Non vuoi perdere gli errori di codifica UTF-8. Prova export PERL5OPTS=-Mwarnings=FATAL,utf8. E assicurati che i tuoi flussi di input siano sempre binmoded :encoding(UTF-8), non solo a :utf8.

  8. I punti di codice tra 128–255 devono essere intesi da 🐪 come i corrispondenti punti di codice Unicode, non solo valori binari non proposti. use feature "unicode_strings"o export PERL5OPTS=-Mfeature=unicode_strings. Quello farà uc("\xDF") eq "SS"e "\xE9" =~ /\w/. Un semplice export PERL5OPTS=-Mv5.12o migliore otterrà anche quello.

  9. I caratteri Unicode nominati non sono abilitati per impostazione predefinita, quindi aggiungi export PERL5OPTS=-Mcharnames=:full,:short,latin,greeko alcuni di questi. Vedi uninames e tcgrep .

  10. È quasi sempre necessario accedere alle funzioni dal modulo standardUnicode::Normalize vari tipi di decomposizioni. export PERL5OPTS=-MUnicode::Normalize=NFD,NFKD,NFC,NFKDe quindi esegui sempre le cose in entrata tramite NFD e quelle in uscita da NFC. Non ci sono ancora livelli I / O per questi di cui sono a conoscenza, ma vedi nfc , nfd , nfkd e nfkc .

  11. Confronti tra stringhe nelle 🐪 utilizzando eq, ne, lc, cmp, sort, & c & CC hanno sempre torto. Quindi, invece di @a = sort @b, è necessario @a = Unicode::Collate->new->sort(@b). Potrebbe anche aggiungerlo al tuo export PERL5OPTS=-MUnicode::Collate. È possibile memorizzare nella cache la chiave per confronti binari.

  12. 🐪 i built-in gradiscono printfe writefanno la cosa sbagliata con i dati Unicode. È necessario utilizzare il Unicode::GCStringmodulo per il primo, sia per quello che per il Unicode::LineBreakmodulo . Vedi uwc e unifmt .

  13. Se vuoi che contino come numeri interi, dovrai eseguire le tue \d+acquisizioni attraverso la Unicode::UCD::numfunzione perché l'atoo incorporato (3) di 🐪 non è attualmente abbastanza intelligente.

  14. Avrai problemi di filesystem su 👽 filesystems. Alcuni filesystem impongono silenziosamente una conversione in NFC; altri impongono silenziosamente una conversione in NFD. E altri fanno ancora qualcos'altro. Alcuni addirittura ignorano del tutto la questione, il che porta a problemi ancora maggiori. Quindi devi fare la tua gestione NFC / NFD per rimanere sano di mente.

  15. Tutti i vostri 🐪 codice che coinvolgono a-zo A-Ze tale deve essere cambiato , compreso m//, s///e tr///. Dovrebbe risaltare come una bandiera rossa urlante che il tuo codice è rotto. Ma non è chiaro come debba cambiare. Ottenere le proprietà giuste e comprenderne le cartelle, è più difficile di quanto si pensi. Uso unichar e uniprops ogni singolo giorno.

  16. Il codice che utilizza \p{Lu}è quasi sbagliato quanto il codice che utilizza [A-Za-z]. È necessario utilizzare \p{Upper}invece e conoscere il motivo. Sì, \p{Lowercase}e \p{Lower}sono diversi da \p{Ll}e \p{Lowercase_Letter}.

  17. Il codice che utilizza [a-zA-Z]è anche peggio. E non può usare \pLo \p{Letter}; deve usare \p{Alphabetic}. Non tutti gli alfabeti sono lettere, lo sai!

  18. Se stai cercando 🐪 variabili con /[\$\@\%]\w+/, allora hai un problema. Devi cercare /[\$\@\%]\p{IDS}\p{IDC}*/, e anche questo non sta pensando alle variabili di punteggiatura o alle variabili del pacchetto.

  19. Se stai cercando spazi vuoti, dovresti scegliere tra \he \v, a seconda. E non dovresti mai usare \s, poiché NON SIGNIFICA [\h\v] , contrariamente alla credenza popolare.

  20. Se stai usando \nper un limite di linea, o anche \r\n, allora stai sbagliando. Devi usare \R, che non è lo stesso!

  21. Se non sai quando e se chiamare Unicode :: Stringprep , allora è meglio imparare.

  22. I confronti senza distinzione tra maiuscole e minuscole devono verificare se due cose sono le stesse lettere indipendentemente dai loro segni diacritici e simili. Il modo più semplice per farlo è con il modulo Unicode :: Collate standard. Unicode::Collate->new(level => 1)->cmp($a, $b). Esistono anche eqmetodi e simili, e probabilmente dovresti anche conoscere i metodi matche substr. Questi hanno notevoli vantaggi rispetto agli 🐪 incorporati.

  23. A volte non è ancora abbastanza, e invece è necessario il modulo Unicode :: Collate :: Locale , come in Unicode::Collate::Locale->new(locale => "de__phonebook", level => 1)->cmp($a, $b)invece. Considera che Unicode::Collate::->new(level => 1)->eq("d", "ð")è vero, ma Unicode::Collate::Locale->new(locale=>"is",level => 1)->eq("d", " ð")è falso. Allo stesso modo, "ae" e "æ" sono eqse non usi le localizzazioni, o se usi quella inglese, ma sono diverse nelle impostazioni locali islandesi. E adesso? È difficile, te lo dico io. Puoi giocare con ucsort per provare alcune di queste cose.

  24. Considera come abbinare il modello CVCV (consonsant, vocale, consonante, vocale) nella stringa " niño ". La sua forma NFD - che hai dannatamente meglio ricordato di averla inserita - diventa "nin \ x {303} o". Ora cosa stai per fare? Anche fingendo che sia una vocale [aeiou](il che è sbagliato, a proposito), non sarai in grado di fare qualcosa del genere (?=[aeiou])\X), perché anche in NFD un punto di codice come 'ø' non si decompone ! Tuttavia, testerà uguale a una "o" usando il confronto UCA che ti ho appena mostrato. Non puoi fare affidamento su NFD, devi fare affidamento su UCA.


💩 𝔸 𝕤 𝕤 𝕦 𝕞 𝕖 𝔹 𝕣 𝕠 𝕜 𝕖 𝕟 𝕟 𝕖 𝕤 𝕤 💩


E non è tutto. Ci sono un milione di ipotesi errate che le persone fanno su Unicode. Fino a quando non capiranno queste cose, il loro codice 🐪 verrà infranto.

  1. Il codice che presuppone che possa aprire un file di testo senza specificare che la codifica è interrotta.

  2. Il codice che presuppone che la codifica predefinita sia una sorta di codifica della piattaforma nativa non funzionante.

  3. Il codice che presuppone che le pagine Web in giapponese o cinese occupino meno spazio in UTF ‑ 16 rispetto a UTF ‑ 8 è errato.

  4. Il codice che presuppone che Perl utilizzi UTF ‑ 8 internamente è errato.

  5. Il codice che presuppone che gli errori di codifica generino sempre un'eccezione è errato.

  6. Il codice che presuppone che i punti del codice Perl siano limitati a 0x10_FFFF è errato.

  7. Il codice che presuppone che sia possibile impostare $/qualcosa che funzionerà con qualsiasi separatore di riga valido è errato.

  8. Il codice che assume l'uguaglianza di andata e ritorno sull'involucro del case, come lc(uc($s)) eq $so uc(lc($s)) eq $s, è completamente rotto e sbagliato. Si consideri che l' uc("σ")e uc("ς") sono entrambi "Σ", ma lc("Σ")non può assolutamente tornare sia di quelli.

  9. Il codice che presuppone che ogni punto di codice minuscolo abbia uno distinto in maiuscolo, o viceversa, è rotto. Ad esempio, "ª"è una lettera minuscola senza maiuscole; che entrambi sono "ᵃ"e "ᴬ"sono lettere, ma non sono lettere minuscole; tuttavia, sono entrambi punti di codice in minuscolo senza corrispondenti versioni in maiuscolo. Capito? Essi sono non \p{Lowercase_Letter} , pur essendo entrambi \p{Letter}e \p{Lowercase}.

  10. Il codice che presuppone che la modifica del caso non cambi la lunghezza della stringa è interrotta.

  11. Il codice che presuppone che ci siano solo due casi è rotto. C'è anche titlecase.

  12. Il codice che presuppone che solo le lettere contengano maiuscole e minuscole. Al di là delle sole lettere, risulta che numeri, simboli e persino segni hanno un caso. In effetti, cambiare il caso può persino fare in modo che qualcosa cambi la sua principale categoria generale, come una \p{Mark}trasformazione in a \p{Letter}. Può anche far passare da uno script all'altro.

  13. Il codice che presuppone che il caso non sia mai dipendente dalla locale è rotto.

  14. Il codice che presuppone che Unicode fornisca un fico sulle localizzazioni POSIX è rotto.

  15. Il codice che presuppone che sia possibile rimuovere i segni diacritici per ottenere alla base le lettere ASCII è malvagio, immobile, rotto, danneggiato dal cervello, sbagliato e giustificazione della pena capitale.

  16. Il codice che presuppone che \p{Diacritic}segni e segni diacritici \p{Mark}siano la stessa cosa è rotto.

  17. Codice che presuppone che le \p{GC=Dash_Punctuation}copertine \p{Dash}siano rotte.

  18. Il codice che presuppone trattino, trattini e svantaggi sono la stessa cosa l'uno dell'altro, o che ce n'è solo uno, è rotto e sbagliato.

  19. Il codice che presuppone che ogni punto di codice occupi non più di una colonna di stampa è rotto.

  20. Il codice che presuppone che tutti i \p{Mark}caratteri occupino zero colonne di stampa è rotto.

  21. Il codice che presuppone che i caratteri simili siano uguali è rotto.

  22. Il codice che presuppone che i caratteri che non si assomigliano non siano uguali viene rotto.

  23. Il codice che presuppone che vi sia un limite al numero di punti di codice in una riga a cui solo uno \Xpuò corrispondere è sbagliato.

  24. Il codice che presuppone \Xnon può mai iniziare con a\p{Mark} carattere è sbagliato.

  25. Il codice che presume che \Xnon possa mai contenere due non \p{Mark}caratteri è sbagliato.

  26. Il codice che presuppone che non possa essere utilizzato "\x{FFFF}"è errato.

  27. Il codice che presuppone un punto di codice non BMP che richiede due unità di codice UTF-16 (surrogato) codificherà in due caratteri UTF-8 separati, uno per unità di codice, è errato. Non lo fa: codifica in un singolo punto di codice.

  28. Il codice che transcodifica da UTF ‐ 16 o UTF ‐ 32 con le DBA principali in UTF ‐ 8 viene interrotto se inserisce una DBA all'inizio dell'UTF-8 risultante. È così stupido che l'ingegnere dovrebbe togliersi le palpebre.

  29. Il codice che presuppone che il CESU-8 sia una codifica UTF valida è errato. Allo stesso modo, il codice che pensa di codificare U + 0000 come "\xC0\x80"UTF-8 è rotto e sbagliato. Questi ragazzi meritano anche il trattamento delle palpebre.

  30. Il codice che presuppone che i caratteri puntino >sempre a destra e che <puntino sempre a sinistra sono errati, perché in realtà non lo fanno.

  31. Codice che presuppone che se si emettono prima il carattere Xe quindi il carattere Y, questi verranno visualizzati come XYerrati. A volte no.

  32. Il codice che presuppone che ASCII sia abbastanza buono per scrivere correttamente l'inglese è stupido, miope, analfabeta, rotto, malvagio e sbagliato. Fuori di testa! Se questo sembra troppo estremo, possiamo scendere a compromessi: d'ora in poi potranno digitare solo con l'alluce da un piede. (Il resto verrà registrato.)

  33. Il codice che presuppone che tutti i \p{Math}punti di codice siano caratteri visibili è errato.

  34. Il codice che presuppone che \wcontenga solo lettere, cifre e caratteri di sottolineatura è errato.

  35. Il codice che presuppone che ^e ~siano segni di punteggiatura è errato.

  36. Il codice che presuppone che üabbia un umlaut è sbagliato.

  37. Il codice che crede che cose come contenere qualsiasi lettera sia sbagliato.

  38. Il codice che crede \p{InLatin}è lo stesso di quello che \p{Latin}è terribilmente rotto.

  39. Il codice che ritiene \p{InLatin}quasi sempre utile è quasi certamente sbagliato.

  40. Codice che crede che sia dato $FIRST_LETTERcome prima lettera in qualche alfabeto e $LAST_LETTERcome ultima lettera in quello stesso alfabeto, che [${FIRST_LETTER}-${LAST_LETTER}]abbia qualche significato è quasi sempre completo rotto, sbagliato e insignificante.

  41. Il codice che crede che il nome di qualcuno possa contenere solo determinati personaggi è stupido, offensivo e sbagliato.

  42. Il codice che tenta di ridurre Unicode in ASCII non è semplicemente sbagliato, il suo autore non dovrebbe mai essere autorizzato a lavorare di nuovo nella programmazione. Periodo. Non sono nemmeno sicuro che dovrebbero essere autorizzati a vedere di nuovo, dal momento che ovviamente non li ha fatti molto bene finora.

  43. Il codice che ritiene che ci sia un modo per fingere che le codifiche dei file di testo non esistano sia rotto e pericoloso. Potrebbe anche spingere anche l'altro occhio.

  44. Il codice che converte i caratteri sconosciuti in ?è rotto, stupido, rompiscatole e va contro la raccomandazione standard, che dice di NON FARLO! RTFM perché no.

  45. Il codice che ritiene di poter indovinare in modo affidabile la codifica di un file di testo non contrassegnato è colpevole di un fatale miscuglio di arroganza e ingenuità che solo un fulmine di Zeus risolverà.

  46. Codice che ritiene che tu possa usare 🐪 printflarghezze per riempire e giustificare che i dati Unicode sono rotti e sbagliati.

  47. Il codice che crede una volta che si crea correttamente un file con un determinato nome, che quando si esegue lso readdirnella sua directory allegata, si trova effettivamente quel file con il nome con cui lo si è creato è difettoso, rotto e sbagliato. Smetti di essere sorpreso da questo!

  48. Il codice che ritiene che UTF-16 sia una codifica a larghezza fissa è stupido, rotto e sbagliato. Revoca la loro licenza di programmazione.

  49. Il codice che tratta i punti del codice da un piano uno in modo diverso da quelli di qualsiasi altro piano è ipso facto rotto e sbagliato. Torna a scuola.

  50. Codice che crede che cose come queste /s/ipossano solo corrispondere "S"o "s"siano rotte e sbagliate. Saresti sorpreso.

  51. Il codice che utilizza \PM\pM*per trovare i grappoli anziché usare \Xè rotto e sbagliato.

  52. Le persone che vogliono tornare nel mondo ASCII dovrebbero essere incoraggiate con tutto il cuore a farlo, e in onore del loro glorioso aggiornamento dovrebbero essere fornite gratuitamente con una macchina da scrivere manuale pre-elettrica per tutte le loro esigenze di immissione dei dati. I messaggi inviati devono essere inviati tramite un telegrafo di 40 caratteri per riga e consegnati a mano da un corriere. FERMARE.


😱 𝕾 𝖀 𝕸 𝕸 𝕬 𝕽 𝖄 😱


Non so quanto più "Unicode predefinito in 🐪" puoi ottenere da quello che ho scritto. Bene, sì, lo so: dovresti usare Unicode::CollateeUnicode::LineBreak , anche. E probabilmente di più.

Come si vede, ci sono troppe cose Unicode che realmente non dovete preoccuparvi di per lì per sempre esiste alcuna cosa come “default a Unicode”.

Quello che scoprirai, proprio come abbiamo fatto in 🐪 5.8, è semplicemente impossibile imporre tutte queste cose sul codice che non è stato progettato fin dall'inizio per renderle conto. Il tuo egoismo ben intenzionato ha appena rotto il mondo intero.

E anche una volta che lo fai, ci sono ancora problemi critici che richiedono una grande quantità di pensiero per ottenere il giusto. Non è possibile attivare l'interruttore. Nient'altro che cervello, e intendo il cervello reale , basterà qui. C'è un sacco di roba che devi imparare. Modulo il ritiro alla macchina da scrivere manuale, semplicemente non puoi sperare di intrufolarti nell'ignoranza. Questo è il 21 ° secolo e non puoi desiderare che Unicode si allontani per ignoranza intenzionale.

Devi impararlo Periodo. Non sarà mai così facile che "tutto funzioni ", perché ciò garantirà che molte cose non funzionino, il che invalida il presupposto che possa mai esserci un modo per "far funzionare tutto".

Potresti essere in grado di ottenere alcune impostazioni predefinite ragionevoli per poche e molto limitate operazioni, ma non senza pensare alle cose molto più di quanto pensi tu abbia.

Come solo un esempio, l'ordinamento canonico sta causando alcuni veri mal di testa. 😭 "\x{F5}" 'õ' , "o\x{303}" 'õ' , "o\x{303}\x{304}" 'ȭ' e "o\x{304}\x{303}" 'ō̃' dovrebbero corrispondere a 'õ' , ma come farai? Questo è più difficile di quanto sembri, ma è qualcosa di cui devi tener conto. 💣

Se c'è una cosa che so di Perl, è quello che fanno e non fanno i suoi bit Unicode, e questa cosa ti prometto: “̲ᴛ̲ʜ̲ᴇ̲ʀ̲ᴇ̲ ̲ɪ̲s̲ ̲ɴ̲ᴏ̲ ̲U̲ɴ̲ɪ̲ᴄ̲ᴏ̲ᴅ̲ᴇ̲ ̲ᴍ̲ᴀ̲ɢ̲ɪ̲ᴄ̲ ̲ʙ̲ᴜ̲ʟ̲ʟ̲ᴇ̲ᴛ̲ ̲” 😞

Non puoi semplicemente modificare alcune impostazioni predefinite e ottenere una navigazione fluida. È vero che corro 🐪 con PERL_UNICODEset to "SA", ma questo è tutto, e anche questo è principalmente per roba da riga di comando. Per un vero lavoro, passo attraverso tutti i molti passaggi descritti sopra e lo faccio molto, molto ** molto attentamente.


😈 ¡ƨdləɥ ƨᴉɥʇ ədoɥ puɐ ʻλɐp əɔᴉu ɐ əʌɐɥ ʻʞɔnl poo⅁ 😈


56
Come ha sottolineato Sherm Pendley: "Tutti!". Se scrivo oggi qualcosa di nuovo, UTF-8 dovrebbe essere il modo più semplice per fare le cose. Non è. La tua caldaia lo proietta. Non tutti hanno una tale conoscenza per trasformare così tanti bicchieri nella giusta posizione. Mi dispiace, ho avuto una giornata lunga e difficile, quindi domani commenterò maggiormente con esempi.
sett.

17
Una conclusione dovrebbe essere ovvia leggendo l'elenco sopra: non piegare mai. Non farlo. Mai. Computazionalmente costoso e con semantica che dipendono in modo cruciale da qualunque cosa sia quella "localizzazione" tenta senza successo di identificarsi.
Tim Bray,

72
Sono l'unico che trova ironico che questo post di tchrist renda così selvaggiamente diverso su FF / Chrome / IE / Opera, a un certo punto fino al punto di essere illeggibile?
danneggiamento del

15
Mentre in genere mi piace il post e ho votato, una cosa mi infastidisce. C'è molto "codice che ... è rotto". Mentre non discuto con l'affermazione, penso che sarebbe bello mostrare la rottura. In questo modo attraverserebbe (questa parte della risposta) da un rant, all'istruzione.

36
@xenoterracide No Non ho usato punti di codice intenzionalmente problematici; è una trama per farti installare il super fantastico carattere Symbola di George Douros , che copre Unicode 6.0. 😈 @depesz Non c'è spazio qui per spiegare perché ogni assunzione rotta sia sbagliata. @leonbloy Molti e molti di questi si applicano a Unicode in generale, non solo a Perl. Parte di questo materiale potrebbe apparire in 🐪 Programming Perl 🐪, 4a edizione , che uscirà a ottobre. 🎃 Mi resta un mese per ✍ lavorarci su e Unicode è is lì; anche
regexes

96

Esistono due fasi per l'elaborazione del testo Unicode. Il primo è "come posso inserirlo ed emetterlo senza perdere informazioni". Il secondo è "come tratto il testo secondo le convenzioni della lingua locale".

Il post di tchrist copre entrambi, ma la seconda parte è da dove proviene il 99% del testo nel suo post. La maggior parte dei programmi non gestisce nemmeno correttamente l'I / O, quindi è importante capire che prima ancora di iniziare a preoccuparsi della normalizzazione e delle regole di confronto.

Questo post mira a risolvere quel primo problema

Quando leggi i dati in Perl, non importa quale codifica sia. Alloca un po 'di memoria e ripone i byte lì. Se diciprint $str , cancella semplicemente quei byte sul tuo terminale, che probabilmente è impostato per assumere che tutto ciò che è scritto su di esso sia UTF-8, e il tuo testo appare.

Meravigliosa.

Tranne che non lo è. Se provi a trattare i dati come testo, noterai che sta succedendo qualcosa di brutto. Non devi fare altro che lengthvedere che ciò che Perl pensa della tua stringa e che cosa pensi della tua stringa non sono d'accordo. Scrivi una riga come: perl -E 'while(<>){ chomp; say length }'e digita 文字化けe otterrai 12 ... non la risposta corretta, 4.

Questo perché Perl presume che la tua stringa non sia testo. Devi dirgli che è un testo prima che ti dia la risposta giusta.

È abbastanza facile; il modulo Encode ha le funzioni per farlo. Il punto di ingresso generico è Encode::decode(ouse Encode qw(decode) , ovviamente). Quella funzione prende una stringa dal mondo esterno (ciò che chiameremo "ottetti", un modo stravagante di dire "byte a 8 bit"), e la trasforma in un testo che Perl capirà. Il primo argomento è un nome di codifica dei caratteri, come "UTF-8" o "ASCII" o "EUC-JP". Il secondo argomento è la stringa. Il valore restituito è lo scalare Perl contenente il testo.

(C'è anche Encode::decode_utf8, che presuppone UTF-8 per la codifica.)

Se riscriviamo il nostro one-liner:

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

Digitiamo 文字 化 け e otteniamo "4" come risultato. Successo.

Questa, proprio lì, è la soluzione al 99% dei problemi Unicode in Perl.

La chiave è, ogni volta che un testo entra nel tuo programma, devi decodificarlo. Internet non può trasmettere caratteri. I file non possono memorizzare caratteri. Non ci sono caratteri nel tuo database. Ci sono solo ottetti e non puoi trattare gli ottetti come personaggi in Perl. È necessario decodificare gli ottetti codificati in caratteri Perl con il modulo Encode.

L'altra metà del problema è ottenere dati dal tuo programma. È facile; dite semplicemente use Encode qw(encode), decidete in che codifica saranno i vostri dati (UTF-8 ai terminali che comprendono UTF-8, UTF-16 per i file su Windows, ecc.), e quindi emettete il risultato encode($encoding, $data)invece di emetterlo $data.

Questa operazione converte i personaggi di Perl, su cui opera il tuo programma, in ottetti che possono essere utilizzati dal mondo esterno. Sarebbe molto più semplice se potessimo semplicemente inviare caratteri su Internet o ai nostri terminali, ma non possiamo: solo ottetti. Quindi dobbiamo convertire i caratteri in ottetti, altrimenti i risultati non sono definiti.

Riassumendo: codificare tutti gli output e decodificare tutti gli input.

Ora parleremo di tre problemi che lo rendono un po 'impegnativo. Il primo sono le biblioteche. Gestiscono il testo correttamente? La risposta è ... ci provano. Se scarichi una pagina Web, LWP ti restituirà il risultato come testo. Se si chiama il metodo giusto sul risultato, questo è (e quello sembra essere decoded_content, non content, che è solo il flusso di ottetti che ha ottenuto dal server.) I driver del database possono essere traballanti; se usi DBD :: SQLite con solo Perl, funzionerà, ma se qualche altro strumento ha messo il testo memorizzato come codifica diversa da UTF-8 nel tuo database ... beh ... non verrà gestito correttamente fino a quando non scrivi il codice per gestirlo correttamente.

Generare i dati di solito è più semplice, ma se vedi "carattere largo nella stampa", sai che stai incasinando la codifica da qualche parte. Quell'avvertimento significa "hey, stai cercando di far trapelare personaggi Perl nel mondo esterno e non ha alcun senso". Il tuo programma sembra funzionare (perché l'altra estremità di solito gestisce correttamente i caratteri Perl non elaborati), ma è molto rotto e potrebbe smettere di funzionare in qualsiasi momento. Risolvilo con un esplicito Encode::encode!

Il secondo problema è il codice sorgente codificato UTF-8. A meno che tu non dica use utf8all'inizio di ogni file, Perl non supporrà che il tuo codice sorgente sia UTF-8. Ciò significa che ogni volta che dici qualcosa del genere my $var = 'ほげ', stai iniettando immondizia nel tuo programma che distruggerà tutto in modo orribile. Non devi "usare utf8", ma se non lo fai, non devi usare caratteri non ASCII nel tuo programma.

Il terzo problema è come Perl gestisce il passato. Molto tempo fa, non esisteva nulla come Unicode e Perl supponeva che tutto fosse in latino-1 testo o binario. Quindi, quando i dati entrano nel tuo programma e inizi a trattarli come testo, Perl tratta ogni ottetto come un carattere Latino-1. Ecco perché, quando abbiamo chiesto la lunghezza di "文字 化 け", abbiamo ottenuto 12. Perl ha ipotizzato che stessimo operando sulla stringa Latin-1 "æååã" (che è di 12 caratteri, alcuni dei quali non stampabili).

Questo si chiama "aggiornamento implicito", ed è una cosa perfettamente ragionevole da fare, ma non è quello che vuoi se il tuo testo non è Latin-1. Ecco perché è fondamentale decodificare esplicitamente l'input: se non lo fai, Perl lo farà e potrebbe sbagliare.

Le persone si imbattono in problemi in cui metà dei loro dati è una stringa di caratteri corretta e alcuni sono ancora binari. Perl interpreterà la parte che è ancora binaria come se fosse un testo in latino-1 e poi la combinerà con i dati dei caratteri corretti. Questo farà sembrare che gestire i tuoi personaggi abbia rotto correttamente il tuo programma, ma in realtà non l'hai risolto abbastanza.

Ecco un esempio: hai un programma che legge un file di testo con codifica UTF-8, ti imbatti in un Unicode PILE OF POOsu ogni riga e lo stampi. Lo scrivi come:

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

E quindi esegui alcuni dati codificati UTF-8, come:

perl poo.pl input-data.txt

Stampa i dati UTF-8 con una cacca alla fine di ogni riga. Perfetto, il mio programma funziona!

Ma no, stai solo facendo una concatenazione binaria. Stai leggendo ottetti dal file, rimuovendo a \ncon chomp e quindi virando sui byte nella rappresentazione UTF-8 del PILE OF POOpersonaggio. Quando rivedi il tuo programma per decodificare i dati dal file e codificare l'output, noterai che ottieni spazzatura ("ð ©") invece della cacca. Questo ti porterà a credere che la decodifica del file di input sia la cosa sbagliata da fare. Non è.

Il problema è che la cacca viene implicitamente aggiornata come latin-1. Se devi use utf8rendere il testo letterale anziché binario, allora funzionerà di nuovo!

(Questo è il problema numero uno che vedo quando aiuto le persone con Unicode. Hanno fatto la parte giusta e hanno interrotto il loro programma. Questo è ciò che è triste per i risultati indefiniti: puoi avere un programma di lavoro per molto tempo, ma quando inizi a ripararlo, non si preoccupa, se stai aggiungendo istruzioni di codifica / decodifica al tuo programma e si interrompe, significa solo che hai più lavoro da fare. La prossima volta, quando progetti con Unicode in mente dall'inizio, sarà molto più facile!)

Questo è davvero tutto ciò che devi sapere su Perl e Unicode. Se dici a Perl quali sono i tuoi dati, ha il miglior supporto Unicode tra tutti i linguaggi di programmazione più diffusi. Se supponi che saprà magicamente che tipo di testo lo stai alimentando, però, eliminerai i tuoi dati in modo irrevocabile. Solo perché il tuo programma funziona oggi sul tuo terminale UTF-8 non significa che funzionerà domani su un file codificato UTF-16. Quindi rendilo sicuro ora e risparmia il mal di testa di cestinare i dati dei tuoi utenti!

La parte facile della gestione di Unicode è la codifica dell'output e della decodifica dell'input. La parte difficile è trovare tutti i tuoi input e output e determinare quale codifica è. Ma è per questo che ottieni un sacco di soldi :)


Il principio è spiegato bene, ma manca l'approccio pratico per l'I / O. L'uso esplicito del Encodemodulo è noioso e soggetto a errori, e rende davvero dolorosa la lettura del codice relativo all'I / O. I livelli I / O forniscono una soluzione in quanto codificano e decodificano in modo trasparente, ove necessario. opene binmodeconsentire le loro specifiche, e pragma openimposta le impostazioni predefinite, come tchrist raccomanda nella sua risposta.
Palec,

48

Siamo tutti d'accordo sul fatto che si tratti di un problema difficile per molte ragioni, ma è proprio questa la ragione per cercare di rendere più facile per tutti.

C'è un modulo recente su CPAN, utf8 :: all , che tenta di "attivare Unicode. Tutto".

Come è stato sottolineato, non è possibile magicamente rendere l'intero sistema (programmi esterni, richieste Web esterne, ecc.) Utilizzare anche Unicode, ma possiamo lavorare insieme per rendere strumenti sensibili che semplificano la risoluzione dei problemi comuni. Questo è il motivo per cui siamo programmatori.

Se utf8 :: all non fa qualcosa che pensi che dovrebbe, miglioriamolo per renderlo migliore. Oppure creiamo strumenti aggiuntivi che insieme possano soddisfare al meglio le diverse esigenze delle persone.

`


5
Vedo molto spazio per miglioramenti nel utf8::allmodulo citato . È stato scritto prima della unicode_stringsfunzione, che Fɪɴᴀʟʟʏ ᴀɴᴅ ᴀᴛ Lᴏɴɢ Lᴀsᴛ corregge le regex per averne una /u. Non sono convinto che sollevi un'eccezione sugli errori di codifica, ed è qualcosa che devi davvero avere. Non viene caricato nel use charnames ":full"pragma, che non è stato ancora caricato automaticamente. Non avvisa [a-z]e simili, printflarghezze di stringa, usando al \nposto di \Re .invece di \X, ma forse sono più una Perl::Criticquestione. Se fossi io, aggiungerei 𝐍𝐅𝐃 in e 𝐍𝐅𝐂 out.
tchrist,

13
@tchrist Il tracker del problema per utf8 :: all è qui. github.com/doherty/utf8-all/issues Vorrebbero ascoltare i tuoi suggerimenti.
Schwern,

4
@Schwern: ᴇɴᴏᴛᴜɪᴛs, ma sentiti libero di rubare e pizzicare le cose che ho scritto qui. Ad essere sincero, sto ancora sentendo / imparando cosa si può fare vs cosa si dovrebbe fare e dove. Ecco un bel esempio fuori scaricando l'ordinamento: unichars -gs '/(?=\P{Ll})\p{Lower}|(?=\P{Lu})\p{Upper}/x' | ucsort --upper | cat -n | less -r. Allo stesso modo, anche piccoli passaggi di preelaborazione ... | ucsort --upper --preprocess='s/(\d+)/sprintf "%#012d", $1/ge'possono essere davvero belli e non vorrei prendere le decisioni degli altri per loro. Sto ancora costruendo la mia cassetta degli attrezzi Unicode .
tchrist,

35

Penso che tu abbia frainteso Unicode e il suo rapporto con Perl. Indipendentemente dal modo in cui memorizzi i dati, Unicode, ISO-8859-1 o molte altre cose, il tuo programma deve sapere come interpretare i byte che riceve come input (decodifica) e come rappresentare le informazioni che vuole produrre (codifica ). Sbagli quell'interpretazione e metti in agitazione i dati. Non c'è alcuna impostazione magica di default nel tuo programma che spiegherà come agire al di fuori del tuo programma.

Pensi che sia difficile, molto probabilmente, perché sei abituato a tutto ciò che è ASCII. Tutto ciò a cui avresti dovuto pensare è stato semplicemente ignorato dal linguaggio di programmazione e da tutte le cose con cui doveva interagire. Se tutto non usasse altro che UTF-8 e tu non avessi altra scelta, allora UTF-8 sarebbe altrettanto facile. Ma non tutto usa UTF-8. Ad esempio, non vuoi che il tuo handle di input pensi che stia ottenendo ottetti UTF-8 a meno che non lo sia effettivamente, e non vuoi che i tuoi handle di output siano UTF-8 se la cosa che legge da loro può gestire UTF-8 . Perl non ha modo di conoscere quelle cose. Ecco perché sei il programmatore.

Non penso che Unicode in Perl 5 sia troppo complicato. Penso che sia spaventoso e la gente lo eviti. C'è una differenza A tal fine, ho inserito Unicode Learning Perl, 6a edizione , e ci sono molte cose Unicode nella programmazione efficace di Perl . Devi dedicare del tempo per imparare e capire Unicode e come funziona. Altrimenti non sarai in grado di usarlo in modo efficace.


3
Penso che tu abbia un punto: è spaventoso. Dovrebbe essere? Per me è la benedizione Unicode, usarlo in Perl5 non lo è (non presumo che nulla sia ASCII, la mia lingua madre ha bisogno almeno di iso8859-4). Ho installato Rakudo e tutto ciò che ho provato con UTF-8 (in questo sandbox limitato) ha funzionato. Ho dimenticato qualcosa? Lo sottolineo di nuovo: è bene avere un supporto Unicode ottimizzato, ma nella maggior parte dei casi non è necessario. Per allontanare la paura dall'argomento, un modo è che tutti leggono molto per capire gli interni. Altro: abbiamo un pragma speciale, quindi rendiamo use utf8_everywherefelici le persone. Perché non l'ultimo?
sett.

3
Penso ancora che ti stia perdendo il punto. Che cosa ha funzionato? Non hai bisogno di capire gli interni. È necessario comprendere gli esterni e come gestire le stringhe con codifiche diverse e rappresentazioni diverse degli stessi caratteri. Leggi di nuovo i consigli di Tom. La maggior parte di quello che dice scommetto che scoprirai che Rakudo non si occupa di te.
brian d foy,

1
@wk: leggi di nuovo la risposta di Randy. Ti ha già detto quali sono i limiti.
brian d foy,

2
@brian d foy: penso che quelle limitazioni vadano bene, come dice Tchrist, non esiste un proiettile magico per ogni aspetto (lo ammetto: non li ho visti prima di porre questa domanda qui). Quindi, quando copriamo un sacco di cose di base con qualcosa come utf8 :: all, non è necessario che tutti costruiscano la propria enorme piastra di caldaia solo per far funzionare le basi della gestione di utf8. Con "nessuna paura" intendo: tutti possono iniziare i suoi progetti sapendo che le basi sono coperte. Sì, hai ragione, ci sono ancora molti problemi. Ma quando iniziare è più facile, avremo più persone coinvolte nel risolverli. IMHO
sett

1
@wk - l'unico "sbagliato" con "utf8: all" o "uni :: perl è solo uno - non sono nel CORE - quindi tutti devono installarlo dal CPAN. E se pensi che questo non sia un grande affare - ripensaci per favore - sì, è più facile usare utf8 con un modulo helper. Senza di esso, il CORE perl ha ancora il supporto unicode - ma è molto complicato. E questo è sbagliato.
jm666,

28

Durante la lettura di questo thread, ho spesso l'impressione che le persone stiano usando " UTF-8 " come sinonimo di " Unicode ". Si prega di fare una distinzione tra i "Code-Point" di Unicode che sono un parente allargato del codice ASCII e le varie "codifiche" di Unicode. E ce ne sono alcuni, di cui UTF-8, UTF-16 e UTF-32 sono quelli attuali e alcuni altri sono obsoleti.

Per favore, UTF-8 (così come tutte le altre codifiche ) esiste e ha significato solo in input o in output. Internamente, dal Perl 5.8.1, tutte le stringhe vengono mantenute come "punti di codice" Unicode. È vero, devi abilitare alcune funzionalità come precedentemente coperte in modo ammirevole.


19
Sono d'accordo che le persone troppo spesso confondono Uɴɪᴄᴏᴅᴇ con UTF-8⧸16⧸32, ma fondamentalmente e criticamente non è vero che Uɴɪᴄᴏᴅᴇ è solo un set di caratteri ingrandito rispetto a ᴀsᴄɪɪ. Al massimo, non è altro che un semplice ɪsᴏ ‑ 10646 . Uɴɪᴄᴏᴅᴇ include molto di più : regole per regole di confronto, piegatura di maiuscole, forme di normalizzazione, cluster di grafemi, interruzione di parole e righe, script, equivoci numerici, larghezze, bidirezionalità, varianti di glifi, comportamento contestuale, locali, regex, classi di combinazione, centinaia di proprietà, e molto di più‼
tchrist

15
@tchrist: il primo passo è ottenere i dati nel tuo programma e nel mondo esterno senza distruggerli. allora puoi preoccuparti di regole di confronto, piegatura delle custodie, varianti di glifi, ecc. piccoli passi.
jrockway,

7
Sono d'accordo, ottenere perl di non eliminare input o output deve essere la prima priorità. Quello che vorrei era avere un modulo o un pragma che potesse incarnare la seguente conversazione fittizia: "- Caro Perl. Per questo programma, tutti gli input e output saranno esclusivamente UTF-8. Potresti per favore non cestinare i miei dati? - Quindi dici solo UFT-8. Sei sicuro? - Sì. - Davvero, davvero sicuro? - Assolutamente.- E accetti che potrei comportarmi in modo strano se mi vengono offerti dati non UTF-8? - Sì, va bene. - Va bene allora."
hlovdal

10

C'è una quantità davvero terrificante di codice antico in circolazione, in gran parte sotto forma di moduli CPAN comuni. Ho scoperto che devo essere abbastanza attento ad abilitare Unicode se uso moduli esterni che potrebbero essere interessati da esso, e sto ancora cercando di identificare e correggere alcuni errori relativi a Unicode in diversi script Perl che uso regolarmente (in particolare, iTiVo fallisce male su tutto ciò che non è ASCII a 7 bit a causa di problemi di transcodifica).


Intendevo usare l' -Copzione per assicurarmi che Perl fosse sulla stessa pagina in cui sono Unicode, perché continuo a fargli decidere di usare ISO 8859/1 invece di Unicode anche se sto impostando esplicitamente $LANGe $LC_ALLcorrettamente. (Questo potrebbe effettivamente riflettere i bug nelle librerie locali della piattaforma.) Qualunque cosa sia, è stato molto fastidioso non poter usare iTivo su programmi con accenti in essi perché gli script Perl che fanno il lavoro cadono con errori di conversione.
geekosaur,

3
Un solo -Csenza opzioni è difettoso e soggetto a errori . Rompi il mondo. Imposta l' PERL5OPTinvariabile -Ce vedrai cosa intendo. Abbiamo provato in questo modo nella v5.8 ed è stato un disastro. Semplicemente non puoi e non devi dire ai programmi che non se l'aspettano che ora hanno a che fare con Unicode se gli piace o no. Ci sono anche problemi di sicurezza. Per lo meno, tutto ciò che lo print while <>farà si romperà se passassero dati binari. Così anche tutto il codice del database. Questa è un'idea terribile.
tchrist,

1
Stavo parlando in modo generico, in realtà, non specificamente -Csenza opzioni. L'invocazione specifica con cui avevo lavorato era -CSDA. Detto questo, sono rimasto bloccato con 5.8.x per molto tempo (ciao MacPorts ...), quindi forse faceva parte di esso.
geekosaur,

1
Corro con PERL_UNICODE impostato su SA. È NON POTETE impostarlo D.
tchrist

@tchrist: Alcuni varmint di Perl hanno pubblicato codice che mostra l'uso di -CSDA e PERL_UNICODE = SDA . Si prega di utilizzare la propria influenza nella comunità. Deve essere fermato!
Ashley,

1

È necessario abilitare la funzione di stringhe unicode e questa è l'impostazione predefinita se si utilizza v5.14;

Non dovresti davvero usare identificatori unicode esp. per il codice esterno tramite utf8 poiché sono insicuri in perl5, solo cperl ha ottenuto quel diritto. Vedi ad esempio http://perl11.org/blog/unicode-identifiers.html

Per quanto riguarda utf8 per i tuoi filehandle / stream: devi decidere da solo la codifica dei tuoi dati esterni. Una libreria non può saperlo, e poiché nemmeno libc supporta utf8, i dati utf8 corretti sono rari. C'è più wtf8, l'aberrazione di windows di utf8 in giro.

A proposito: Moose non è in realtà "Modern Perl", hanno semplicemente dirottato il nome. Moose è perfetto perl postmoderno in stile Larry Wall mescolato con stile Bjarne Stroustrup tutto va bene, con un'eclettica aberrazione della corretta sintassi perl6, ad esempio usando stringhe per nomi di variabili, sintassi di campi orribili e un'implementazione ingenua molto immatura che è 10 volte più lenta di una corretta attuazione. cperl e perl6 sono i veri perl moderni, dove la forma segue la funzione e l'implementazione è ridotta e ottimizzata.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.