Kodėl „Modern Perl“ pagal nutylėjimą vengia UTF-8?

Įdomu, kodėl dauguma modernių „Perl“ sprendimų neleidžia pagal nutylėjimą naudoti „ UTF-8 “.

Suprantu, kad pagrindiniams „Perl“ scenarijai yra daug pasenusių problemų, kai tai gali sutrikdyti darbą. Tačiau, mano nuomone, XXI amžiuje dideli nauji projektai (arba projektai, turintys didelę perspektyvą) turėtų padaryti savo UTF-8 programinės įrangos įrodymus nuo nulio. Tačiau nematau. Pavyzdžiui, Moose leidžia griežtus įspėjimus, bet ne Unicode . „Modern :: Perl“ taip pat sumažina modelį, tačiau be UTF-8 apdorojimo.

Kodėl Ar yra priežasčių 2011 m. Vengti UTF-8 šiuolaikiniuose Perl projektuose?


„@Tchrist“ komentaras yra per ilgas, todėl aš jį priduriu čia.

Panašu, kad situacija neaiškėja. Leiskite pabandyti pridėti keletą dalykų.

Tchristas , ir matau situaciją gana panašiai, bet mūsų išvados yra visiškai priešingos. Sutinku, kad situacija su Unicode yra sudėtinga, tačiau būtent todėl mes („Perl“ naudotojai ir koduotojai) reikia tam tikro sluoksnio (ar pragmos), todėl UTF-8 tvarkymas yra toks pat paprastas kaip šiandien.

Tchristas atkreipė dėmesį į daugelį aspektų, kuriuos reikės padengti, aš jas perskaitysiu ir mąstysiu kelias dienas ar net savaites. Tačiau tai nėra mano požiūris. Tchristas bando įrodyti, kad nėra vieno būdo „įgalinti UTF-8“. Aš neturiu daug žinių, kad galėčiau ginčytis. Taigi, seku gyvais pavyzdžiais.

Aš grojau su Rakudo , o UTF-8 ten buvo, nes man reikėjo . Aš neturėjau problemų, ji tiesiog dirbo. Galbūt kai kur giliau yra apribojimų, bet pradžioje viskas, ką aš išbandžiau, dirbo taip, kaip tikėjausi.

Argi tai neturėtų būti šiuolaikinio Perl 5 tikslas? Aš tai dar labiau pabrėžiu: aš nerekomenduoju UTF-8 kaip numatytąjį „Perl“ branduolio simbolių rinkinį, siūlau galimybę ją paleisti , padedant tiems, kurie rengia naujus projektus.

Kitas pavyzdys, tačiau neigiamas tonas. Ši sistema turėtų palengvinti plėtros procesą. Prieš kelerius metus bandžiau naudotis internetinėmis sistemomis, bet tiesiog juos išmetiau, nes „UTF-8 įtraukimas“ buvo toks neaiškus. Neradau, kaip ir kur prijungti Unicode palaikymą. Tai buvo taip ilgai, kad man tapo lengviau eiti senuoju keliu. Dabar aš pamačiau dosnumą, kad susidorotų su ta pačia problema su Masonu 2: Kaip padaryti, kad Mason2 UTF-8 būtų švarus? . Taigi tai yra gana nauja struktūra, tačiau naudojant UTF-8 reikia gilių žinių apie jos vidinius komponentus. Atrodo didelis raudonas ženklas: STOP, nenaudokite manęs!

Man labai patinka Perl. Bet darbas su Unicode yra skausmingas. Aš vis dar susiduriu su sienomis. Tam tikra prasme tchristas yra teisingas ir atsako į mano klausimus: nauji projektai nepritraukia UTF-8, nes Perl 5 tai pernelyg sudėtinga.

509
28 мая '11 в 18:12 2011-05-28 18:12 Wk nustatė gegužės 28 d., 11 val. 18:12 2011-05-28 18:12
@ 6 atsakymai

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


𝓔𝓭𝓲𝓽: 𝙎𝙞𝙢𝙥𝙡𝙚𝙨𝙩 ℞: 𝟕 𝘿𝙞𝙨𝙘𝙧𝙚𝙩𝙚 𝙍𝙚𝙘𝙤𝙢𝙢𝙚𝙣𝙙𝙖𝙩𝙞𝙤𝙣𝙨

  • Nustatykite PERL_UNICODE į kintamąjį AS . Dėl to visi „Perl“ scenarijai iššifruoja @ARGV kaip UTF-8 eilutes ir nustato visų trijų stdin, stdout ir stderr kodavimą į UTF-8. Abu yra pasauliniai padariniai, o ne leksiniai.

  • Šaltinio failo viršuje (programa, modulis, biblioteka, „hickey“) aiškiai nurodau, kad naudojate „Perl“ 5.12 ar naujesnę versiją, naudodami:

    use v5.12; # minimal for unicode string feature

    use v5.14; # optimal for unicode string feature

  • Įtraukite įspėjimus, kaip ir ankstesniame pranešime leidžiama naudoti tik griežtesnes ir funkcijas, o ne įspėjimus. Aš taip pat siūlau reklamuoti Unicode įspėjimus dėl išimčių, todėl naudokite abi šias eilutes, o ne tik vieną iš jų. Tačiau atkreipkite dėmesį, kad pagal v5.14, įspėjimo klasė utf8 turi tris kitas nonchar , kurios gali būti įjungtos atskirai: nonchar , surrogate ir non_unicode . Galbūt norėsite padidinti valdymą.

    use warnings;

    use warnings qw( FATAL utf8 );

  • Praneškite, kad šis šaltinio blokas yra užkoduotas kaip UTF-8. Nors ši pragma kažkada darė kitus dalykus, dabar ji tarnauja vieninteliam tikslui ir niekam kitam:

    use utf8;

  • Patvirtinti, kad viskas, kas atveria failų rankenas šioje leksinėje srityje, bet ne kitur, turėtų daryti prielaidą, kad šis srautas yra užkoduotas UTF-8, jei nenurodote kitaip. Taigi, jūs neturite įtakos kitiems moduliams ar kitiems programos kodams.

    use open qw( :encoding(UTF-8) :std );

  • Įtraukti vardinius simbolius per \N{CHARNAME} .

    use charnames qw( :full :short );

  • Jei turite DATA deskriptorių, turite aiškiai nurodyti jo kodavimą. Jei norite, kad jis būtų UTF-8, pasakykite:

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

Žinoma, nėra jokio kito tikslo, su kuriuo galėtumėte susidurti, bet tai yra pakankamai, kad priartėtų prie valstybės tikslo: „viskas veikia su UTF-8“, nors šiek tiek silpnesnė šių terminų prasme.

Kita pragma, nors tai netaikoma „Unicode“:

  use autodie; 

Labai rekomenduojama.


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


Sakydamas, kad „Perl turėtų [tam tikru būdu! ] Įjungti Unicode pagal nutylėjimą“, net nepradės galvoti apie tai, kaip gauti, sakydamas, kad kai kurie reti ir pavieniai atvejai yra labai naudingi, Unicode yra daug daugiau, ne tik didesnis simbolių repertuaras; taip pat tai, kaip visi šie simboliai sąveikauja daugeliu būdų.

Netgi nedidelės minimalios priemonės, kurias (kai kurie) žmonės mano, kad jie nori, užtikrins, kad jie nužudys milijonus kodų eilučių, kurie neturi galimybės „atnaujinti“ į naują, naują, drąsų naują pasaulį.

Tai yra daug sunkiau nei žmonės apsimeta. Per pastaruosius kelerius metus apie tai daug galvojau. Norėčiau parodyti, kad aš klystu. Bet aš taip nemanau. Unikodas yra žymiai sudėtingesnis už modelį, kurį norėtumėte jį įdėti, ir čia yra sunku, kad niekada negalėsite nuvalyti po kilimu. Jei bandysite, sugadinsite savo kodą ar kitą. Tam tikru momentu jūs tiesiog turite sugriauti ir sužinoti, kas yra Unicode. Jūs negalite apsimesti, kad tai nėra.

Išeina iš savo kelio, kad Unicode būtų paprastas, daug daugiau nei bet kas kitas, kurį aš kada nors naudoju. Jei manote, kad tai blogai, pabandykite kažką dar kartą. Tada grįžkite į: grįšite į geresnį pasaulį, ar jūs apie tai supažindinate, kad galėtume geriau panaudoti jūsų naujas žinias.


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


Čia bent jau yra keletas dalykų, kurie, atrodo, reikalingi norint „įjungti Unicode pagal nutylėjimą“:

  • Visi pirminiai kodai pagal nutylėjimą turi būti UTF-8. Jūs galite gauti jį use utf8 arba export PERL5OPTS=-Mutf8 .

  • ATA DATA mygtukas turi būti UTF-8. Tai turėsite atlikti pagal paketą, pvz., binmode(DATA, ":encoding(UTF-8)") .

  • Numatytasis programos argumentų rip scenarijų atveju yra suprasti UTF-8. export PERL_UNICODE=A arba perl -CA arba export PERL5OPTS=-CA .

  • Standartiniai įvesties, išvesties ir klaidų srautai turėtų turėti numatytąjį UTF-8 reikšmę. export PERL_UNICODE=S visiems, arba I , O ir / arba E tik kai kuriems iš jų. Tai panaši į perl -CS .

  • Visos kitos rankenėlės atidarytos obs turėtų būti laikomos UTF-8, jei nenurodyta kitaip; export PERL_UNICODE=D arba su I ir O tam tikriems; export PERL5OPTS=-CD veiks. Tai daro -CSAD visiems.

  • Uždenkite abu pagrindus ir visus srautus, kuriuos atidarote export PERL5OPTS=-Mopen=:utf8,:std . Žr.

  • Nenorite praleisti UTF-8 kodavimo klaidų. Pabandykite export PERL5OPTS=-Mwarnings=FATAL,utf8 . Ir įsitikinkite, kad jūsų įvesties srautai visada binmode d :encoding(UTF-8) , o ne tik :utf8 .

  • Kodo taškai tarp 128-255 turėtų būti suprantami kaip atitinkami Unikodo kodo taškai, o ne tik nesukurtos dvejetainės vertės. use feature "unicode_strings" arba export PERL5OPTS=-Mfeature=unicode_strings . Tokiu būdu „ uc("\xDF") eq "SS" ir "\xE9" =~ /\w/ . Tai taip pat bus paprasta export PERL5OPTS=-Mv5.12 arba geriau.

  • Pavadinti Unicode simboliai neįtraukiami pagal nutylėjimą, todėl pridėkite export PERL5OPTS=-Mcharnames=:full,:short,latin,greek arba kai kurie iš jų. Žr. Uninames ir tcgrep .

  • Jums beveik visada reikia prieigos prie standartinių Unicode::Normalize įvairių tipų plėtinių modulių funkcijų. export PERL5OPTS=-MUnicode::Normalize=NFD,NFKD,NFC,NFKD ir tada visada paleiskite gaunamą medžiagą per NFD ir iš NFC siunčiamą medžiagą. Jiems nėra I / O lygio, bet apie tai žinau, bet žr. Nfc , nfd , nfkd ir nfkc .

  • Lyginant stygas ings naudojant eq , ne , lc , cmp , sort cc visada yra neteisinga. Todėl vietoj @a = sort @b jums reikia @a = Unicode::Collate->new->sort(@b) . Tai galite pridėti prie savo export PERL5OPTS=-MUnicode::Collate . Galite talpinti raktą dvejetainiams palyginimams.

  • 🐪 įmontuotos funkcijos, pvz., printf ir write , daro klaidą su Unicode duomenimis. Pirmajam ir abiem bei Unicode::LineBreak turite naudoti Unicode::GCString . Žr. Uwc ir unifmt .

  • Jei norite, kad jie būtų laikomi sveikaisiais skaičiais, turėsite paleisti savo „ \d+ momentinius vaizdus naudodami Unicode::UCD::num funkciją , nes integruotas atoi (3) šiuo metu nėra pakankamai protingas.

  • Problems Failų sistemoje yra problemų su failų sistema. Kai kurios failų sistemos tyliai taiko NFC konversiją; kiti yra tyliai priversti į NFD. Ir kiti daro kažką kitą. Kai kurie netgi ignoruoja šį klausimą, o tai kelia dar didesnių problemų. Taigi, norint išlaikyti funkcionalumą, turite atlikti savo NFC / NFD apdorojimą.

  • Visi jūsų codes kodai, kuriuose yra az arba az , ir tokie turi būti pakeisti , įskaitant m// , s/// ir tr/// . Ji turėtų išsiskirti kaip rėkia raudona vėliava, kuri pažeidžia jūsų kodą. Tačiau neaišku, kaip tai turėtų pasikeisti. Teisingų savybių įgijimas ir jų atsitiktinių klausimų supratimas yra sunkiau nei manote. Kiekvieną dieną naudoju unichars ir uniprops .

  • Kodas, kuris naudoja \p{Lu} yra beveik toks pat klaidingas kaip ir kodas, kuriame naudojamas [A-Za-z] . Vietoj to, turite naudoti \p{Upper} ir žinoti priežastį. Taip, \p{Lowercase} ir \p{Lower} skiriasi nuo \p{Ll} ir \p{Lowercase_Letter} .

  • Kodas, kuris naudoja [A-Za-z] yra dar blogiau. Jis negali naudoti \pL arba \p{Letter} ; jis turėtų naudoti \p{Alphabetic} . Ne visi abėcėlės raidės, žinote!

  • Jei ieškote kintamųjų 🐪 su /[\$\@\%]\w+/ , turėsite problemų. Turite ieškoti /[\$\@\%]\p{IDS}\p{IDC}*/ , ir netgi tai nemano apie skyrybos kintamuosius ar paketų kintamuosius.

  • Jei pažymėsite tarpus, turite pasirinkti tarp \h ir \v . Ir jūs niekada neturėtumėte naudoti, kaip NEŽININKITE , priešingai nei visuotinai.

  • Jei naudojatės linijos pertrauka ar netgi \r\n , tai darote neteisingai. Jūs turite naudoti \R , kuris nėra tas pats!

  • Jei nežinote, kada ir ar norite paskambinti Unicode :: Stringprep , geriau mokytis.

  • Nejautrūs palyginimai turėtų patikrinti, ar du dalykai yra tie patys laiškai, nepriklausomai nuo jų diakritikos ir pan. Paprasčiausias būdas tai padaryti yra naudojant standartinį Unicode :: Collate . Unicode::Collate->new(level => 1)->cmp($a, $b) . Taip pat yra eq metodai ir tt Ir turbūt turėtumėte sužinoti apie match ir substr metodus. Jie turi tam tikrų privalumų, palyginti su įterptiniais įterptiniais moduliais.

  • Kartais to dar nepakanka, ir jums reikia Unicode :: Collate :: Locale modulio , kaip Unicode::Collate::Locale->new(locale => "de__phonebook", level => 1)->cmp($a, $b) vietoj Unicode::Collate::Locale->new(locale => "de__phonebook", level => 1)->cmp($a, $b) . Tarkime, Unicode::Collate::->new(level => 1)->eq("d", "ð") teisinga, bet Unicode::Collate::Locale->new(locale=>"is",level => 1)->eq("d", " ð") yra klaidingas. Panašiai „ae“ ir „æ“ yra eq jei nenaudojate vietinių kalbų arba naudojate anglų kalbą, tačiau jie yra skirtingi islandų kalba. Kas dabar? Sakau jums sunkiai. Galite žaisti su ucsort, kad patikrintumėte kai kuriuos iš šių dalykų.

  • Apsvarstykite, kaip suderinti CVCV modelį (konsonantą, balsį, konsonantą, balsą) eilutėje „niño“. Jo NFD forma, kurią jūs geriau prisiminėte, kad ją įdėtumėte, tampa „nin x {303} o“. Ką jūs darysite? Net apsimesti, kad balsas [aeiou] (beje, taip), jūs negalite kažką panašaus (?=[aeiou])\X) , nes net (?=[aeiou])\X) kodo taškas, kaip ø, nesiskirsto ! Tačiau jis bus išbandytas lyginant su „o, naudojant UCA palyginimą, kurį aš tiesiog parodiau. Jūs negalite pasikliauti NFD, turite pasikliauti UCA.


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


Ir tai dar ne viskas. Yra milijonų klaidingų prielaidų, kurias žmonės daro apie „Unicode“. Kol jie nesupranta šių dalykų, jų kodas bus sugadintas.

  • Kodas, darant prielaidą, kad jis gali atidaryti tekstinį failą nenurodydamas, kad kodavimas neveikia.

  • Kodas, kuris prielaida, kad numatytasis kodavimas yra tam tikras platformos kodavimas.

  • Kodas, kuris numato, kad japonų ar kinų tinklalapiai užima mažiau vietos UTF-16 nei UTF-8, yra neteisingas.

  • Kodas, rodantis, kad Perl naudoja UTF-8, yra viduje neteisingas.

  • Kodas, rodantis, kad kodavimo klaidos visada sukurs išimtį, yra neteisinga.

  • Kodas, rodantis, kad Perl kodo taškai yra apriboti iki 0x10_FFFF, yra neteisingi.

  • Kodas, kuris numato, kad galite nustatyti $/ dirbti su bet kuriuo galiojančiu eilutės ribotuvu.

  • Kodas, kuris prisiima lygiavertį apvalinimą kasečių formavime, pvz., Lc lc(uc($s)) eq $s arba uc(lc($s)) eq $s , yra visiškai sugadintas ir neteisingas. Atkreipkite dėmesį, kad uc("σ") ir uc("ς") "Σ" , bet lc("Σ") negali grąžinti abiejų.

  • Kodas, kuris numato, kad kiekviena mažoji linija turi atskirą didžiųjų raidžių skaičių arba atvirkščiai. Pavyzdžiui, "ª" yra mažoji raidė be didžiųjų raidžių; kadangi "ᵃ" ir "ᴬ" yra raidės, tačiau jos nėra mažosios raidės; tačiau abu jie yra mažųjų kodų taškai be atitinkamų versijų didžiosiomis raidėmis. Ar tai? Jie nėra \p{Lowercase_Letter} , nepaisant to, kad abu yra \p{Letter} ir \p{Lowercase} .

  • Kodas, susijęs su bylos keitimu, nekeičia eilutės ilgio.

  • Kodas, kuriame yra tik du atvejai. Taip pat yra titlase.

  • Kodas, kuris numato, kad yra tik raidės. Pasirodo, kad už raidžių skaičiai, simboliai ir netgi ženklai yra susiję. Tiesą sakant, bylos keitimas gali sukelti kažką pakeisti savo pagrindinę bendrąją kategoriją, pvz., \p{Mark} , kuris tapo \p{Letter} . Jis taip pat gali priversti jį pereiti nuo vieno scenarijaus į kitą.

  • Kodas, kuriame daroma prielaida, kad byla niekada nepriklauso nuo vietovės.

  • Kodas, kuris reiškia, kad Unicode rodo, kad POSIX vietovės yra sugadintos.

  • Kodas, kuris numato, kad galite pašalinti akcentus, kad gautumėte ASCII laiškus ant jų, yra blogis, vis dar yra pažeistas, pažeistas smegenų, neteisingas ir mirties bausmės pasiteisinimas.

  • Kodas, kuris prielaida, kad diakritiniai \p{Diacritic} ir \p{Mark} ženklai yra tas pats, kuris

  • Kodas, kuris reiškia \p{GC=Dash_Punctuation} , apima kaip \p{Dash} .

  • Kodas, kuris prielaida, kad brūkšneliai, brūkšneliai ir minusai yra tokie patys, kaip vienas kitą, arba kad yra tik vienas, sugadintas ir klaidingas.

  • Kodas, kuriame daroma prielaida, kad kiekvienas kodo taškas užima ne daugiau kaip vieną spausdinimo stulpelį. Eik

  • Sugadintas kodas, pagal kurį visi \p{Mark} simboliai užima nulinį spausdinimo stulpelį.

  • Kodas, kuris laikomas tuo pačiu identiškų simbolių pažeidimu.

  • Kodas, pagal kurį daroma prielaida, kad simboliai, kurie nėra panašūs vienas į kitą, nėra panašūs.

  • Kodas, kuris prielaida, kad eilutėje esantis kodo taškų skaičius gali būti ribotas tik su vienu \X

  • Kodas, kuris prisiima \X niekada negali prasidėti simboliu \p{Mark} .

  • Kodas, darant prielaidą, kad \X negali turėti dviejų simbolių, kurie nėra \p{Mark} .

  • Kodas, rodantis, kad jis negali naudoti "\x{FFFF}" yra neteisingas.

  • Kodas, kuriam priskiriamas kitas nei BMP kodas, kuris reikalauja, kad du UTF-16 kodo blokai (pakaitalai) koduotų du atskirus UTF-8 simbolius, po vieną kodo vienetą, yra klaidingi. Tai nėra: ji koduoja vieną kodo tašką.

  • Kodas, kuris transkoduoja iš UTF-16 arba UTF-32 su pirmaujančiomis specifikacijomis UTF-8, nutraukiamas, jei specifikaciją pateikia gauto UTF-8 pradžioje. Tai taip kvaila, kad inžinierius turi turėti savo akių vokus.

  • Kodas, kuris daro prielaidą, kad CESU-8 yra galiojantis UTF kodavimas, yra neteisingas. Be to, kodas, pagal kurį U + 0000 kodavimas laikomas "\xC0\x80" yra UTF-8, yra sugadintas ir neteisingas. Šie vaikinai taip pat nusipelno vokų gydymo.

  • Kodas, kuris prielaida, kad tokie simboliai kaip > visada nukreipiami į dešinę, ir < visada rodo, kad jie neteisingi, nes iš tikrųjų jie nėra.

  • Kodas, kuris prielaida, kad pirmą kartą išvedamas simbolis X , o tada simbolis Y , kuris bus rodomas kaip XY . Kartais jie to nedaro.

  • Kodas, rodantis, kad ASCII yra pakankamai gera, kad teisingai parašytų anglų kalbą, yra kvailas, trumparegiškas, neraštingas, skaldytas, blogas ir neteisingas. Iš galvos! Jei tai atrodo pernelyg kraštutinė, mes galime kompromisą: nuo šiol jie gali spausdinti tik su dideliu pirštu su viena koja (likusi dalis vengia).

  • Kodas, kuris prielaida, kad visos \p{Math} žymos yra

  • Kodas, kuriame laikoma \w yra tik raidės, skaičiai ir \ t

  • Kodas, kuris reiškia, kad ^ ir ~ yra skyrybos ženklai.

  • Kodas, darant prielaidą, kad ü klaidingai priimtas pagal umlaut.

  • Kodas, kuris mano, kad tokie dalykai kaip bet kokios raidės jose yra.

  • Kodas, kuris reiškia, kad \p{InLatin} pats, kaip \p{Latin} .

  • Kodas, kuris sako, kad beveik \p{InLatin} beveik visada naudingas, beveik neabejotinai negerai.

  • Kodas, kuris laikomas nurodytu $FIRST_LETTER pirmuoju raidėmis abėcėlėje ir $LAST_LETTER kaip paskutinė raidė toje pačioje abėcėlėje, kad [${FIRST_LETTER}-${LAST_LETTER}] turi bet kokią reikšmę, beveik visada visiškai neveikiančią ir neteisingą ir beprasmiška.

  • Kodas, kuris mano, kad kažkieno pavadinime gali būti tik tam tikri simboliai, yra kvailas, įžeidžiantis ir neteisingas.