Modern Perl neden varsayılan olarak UTF-8'den kaçınır?


557

Perl kullanılarak oluşturulan modern çözümlerin çoğunun neden varsayılan olarak UTF-8'i etkinleştirmediğini merak ediyorum .

Temel Perl betikleri için bazı şeyleri kırabileceği birçok eski sorun olduğunu anlıyorum. Ama, benim bakış itibaren, 21 st yüzyılda, yeni büyük projeler (ya da büyük bir bakış açısı ile projeler) sıfırdan kendi yazılım UTF-8 kanıt yapmalıdır. Hala olduğunu görmüyorum. Örneğin, Moose katı ve uyarıları etkinleştirir, ancak Unicode'u etkinleştirmez . Modern :: Perl ısıtıcı plakayı da azaltır, ancak UTF-8 kullanımı yoktur.

Neden? 2011 yılında modern Perl projelerinde UTF-8'den kaçınmak için bazı nedenler var mı?


@Tchrist yorum yapmak çok uzun sürdü, bu yüzden buraya ekliyorum.

Görünüşe göre kendimi açıklığa kavuşturmadım. Bazı şeyler eklemeye çalışayım.

tristrist ve ben durumu oldukça benzer görüyoruz, ama sonuçlarımız tamamen zıt uçlarda. Kabul ediyorum, Unicode ile durum karmaşık, ancak bu yüzden (Perl kullanıcıları ve kodlayıcıları) UTF-8 işlemeyi günümüzde olması gerektiği kadar kolay hale getiren bir katmana (veya pragmaya) ihtiyacımız var.

tchrist ele almak için birçok yönü işaret etti, ben günlerce hatta haftalarca onları okuyacağım ve düşüneceğim. Yine de, bu benim görüşüm değil. tchrist "UTF-8'i etkinleştirmenin" tek bir yolu olmadığını kanıtlamaya çalışır. Bununla tartışacak kadar bilgim yok. Ben de canlı örneklere bağlı kaldım.

Rakudo ile oynadım ve UTF-8 tam ihtiyacım olan oradaydı . Herhangi bir sorun yaşamadım, sadece işe yaradı. Belki daha derin bir yerde bazı sınırlamalar vardır, ancak başlangıçta test ettiğim tek şey beklediğim gibi çalıştı.

Modern Perl 5'te de bir hedef olmamalı mı? Daha fazla vurgulamak istiyorum: UTF-8'i çekirdek Perl için varsayılan karakter seti olarak önermiyorum, yeni projeler geliştirenler için bir tetikleme ile tetikleme imkanı öneriyorum .

Başka bir örnek, ama daha olumsuz bir tonla. Çerçeveler gelişimi kolaylaştırmalıdır. Birkaç yıl önce, web çerçevelerini denedim, ancak "UTF-8'i etkinleştirmek" çok belirsiz olduğu için onları attım. Unicode desteğini nasıl ve nerede bağlayacağımı bulamadım. O kadar zaman alıcıydı ki eski yollara gitmeyi daha kolay buldum. Şimdi burada Mason 2 ile aynı problemle başa çıkmak için bir ödül olduğunu gördüm : Mason2 UTF-8'i nasıl temizleyebilirim? . Bu yüzden, oldukça yeni bir çerçevedir, ancak UTF-8 ile kullanılması, içselleri hakkında derin bilgiye ihtiyaç duyar. Büyük kırmızı bir işaret gibi: DUR, beni kullanma!

Perl'i gerçekten çok seviyorum. Ancak Unicode ile uğraşmak acı vericidir. Kendimi hala duvarlara karşı koşarken buluyorum. Bir şekilde hakikat doğru ve sorularıma cevap veriyor: yeni projeler UTF-8'i çekmiyor çünkü Perl 5'te çok karmaşık.


15
Üzgünüm ama @tchrist ile aynı fikirdeyim - UTF-8 son derece zor. Sadece bir anahtarı çeviren ve daha sonra doğru şekilde işleyen bir çerçeve veya araç yoktur. Bu, uygulamanızı tasarlarken doğrudan düşünmeniz gereken bir şeydir - herhangi bir çerçeve veya dilin işleyebileceği bir şey değildir. Eğer rakudo sizin için işe yaradıysa, test vakalarınızla yeterince maceracı değildiniz - çünkü @ tchrist'in cevabı ve kasabındaki birkaç örneği alacaktır.
Billy ONeal

12
Moose veya Modern :: Perl'in tam olarak ne yapmasını umuyorsunuz? Sihirli dosya ve veritabanlarındaki rastgele kodlanmış karakter verilerini tekrar geçerli verilere dönüştürür mü?
jrockway

13
Bu ne anlama geliyor? Geyiğin metin manipülasyonu ile ilgisi yoktur. Neden karakter kodlamasını bilmeli, sizin için varsayılan olanı daha az seçmeli? (Her neyse, listelediğiniz pragmaların kodlamaya dokunmamasının nedeni, konvansiyonun Perl pragmalarının sözcüksel davranışları etkilemesidir . Bu PHP veya Ruby değil.)
jrockway

8
(Ayrıca ... "en Modern Perl uygulamaları" UTF-8 kırmak? Kesinlikle asla bir uygulama yazdım, Perl veya başka türlü, bu Unicode-temiz değil.)
jrockway

11
Nb. tchrist (Tom Christiansen) Unicode hakkında [ training.perl.com/OSCON2011/index.html Tom Christiansen'in OSCON 2011 için Materyalleri] adlı kitabını yayınladı. "Unicode Destek Çekimi: İyi, Kötü ve (çoğunlukla) Çirkin" başlıklı başlık, farklı programlama dillerinde Unicode desteği hakkında konuşuyor. Yalnızca Google Go ve Perl5, tam Unicode için destek sunar, yalnızca Google Go yerleşiktir (Perl6'dan bahsedilmez).
Jakub Narębski

Yanıtlar:


1146

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

  1. PERL_UNICODEDeğişken olarak ayarlayın AS. Bu, tüm Perl betiklerinin @ARGVUTF ‑ 8 dizeleri olarak çözülmesini sağlar ve stdin, stdout ve stderr'in üçünün de kodlamasını UTF ‑ 8 olarak ayarlar. Her ikisi de sözcüksel etkiler değil, küresel etkilerdir.

  2. Kaynak dosyanızın (program, modül, kütüphane, dohickey) üstünde perl sürüm 5.12 veya daha üstünü şu şekilde çalıştırdığınızı öne sürün:

    use v5.12;  # minimal for unicode string feature
    use v5.14;  # optimal for unicode string feature
    
  3. Önceki bildirim yalnızca uyarıları değil, darlıkları ve özellikleri etkinleştirdiğinden uyarıları etkinleştirin. Ayrıca Unicode uyarılarını istisnalara yükseltmeyi öneriyorum, bu yüzden sadece bir tanesini değil, bu iki satırı da kullanın. Not Ancak v5.14 altına alınmasıyla, bu utf8uyarı sınıfı tümü ayrı etkinleştirilebilir diğer üç subwarnings oluşur: nonchar, surrogate, ve non_unicode. Bunlar üzerinde daha fazla kontrol sahibi olmak isteyebilirsiniz.

    use warnings;
    use warnings qw( FATAL utf8 );
    
  4. Bu kaynak birimin UTF ‑ 8 olarak kodlandığını beyan edin. Bir zamanlar bu pragma başka şeyler yaptıysa da, şimdi bu tek başına tek bir amaca hizmet ediyor ve başka hiçbir işe yaramıyor:

    use utf8;
  5. Bu sözcük kapsamı içinde ancak başka bir yerde olmayan bir dosya tanıtıcısı açan herhangi bir şeyin, aksi belirtilmedikçe bu akışın UTF-8'de kodlandığını varsaymak olduğunu beyan edin. Bu şekilde diğer modüllerin veya başka programların kodlarını etkilemezsiniz.

    use open qw( :encoding(UTF-8) :std );
  6. İle adlandırılmış karakterleri etkinleştir \N{CHARNAME}.

    use charnames qw( :full :short );
  7. Bir DATAtanıtıcı varsa, kodlamasını açıkça ayarlamanız gerekir. Bunun UTF ‑ 8 olmasını istiyorsanız şunu söyleyin:

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

Tabii ki sonunda kendinizi bulabileceğiniz diğer konuların sonu yoktur, ancak bunlar, bu terimlerin biraz zayıflamış olmasına rağmen, her şeyin UTF-8 ile çalışmasını sağlamak için devlet hedefine yaklaşmak için yeterli olacaktır.

Unicode ile ilgili olmasa da, diğer bir pragma:

      use autodie;

Şiddetle tavsiye edilir.

🌴 🐪🐫🐪 🌞 𝕲𝖔 𝕿𝖍𝖔𝖚 𝖆𝖓𝖉 𝕯𝖔 𝕷𝖎𝖐𝖊𝖜𝖎𝖘𝖊 🌞 🐪🐫🐪 🐁 Instagram Hesabındaki Resim ve Videoları


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


Bugünlerde kendi demirbaşım şu şekilde gözüküyor:

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__

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


“Perl [bir şekilde! ] varsayılan olarak Unicode'u etkinleştirin "bile, nadir ve izole bir durumda marjinal olarak yararlı olacak kadar söylemeye başlamak için düşünmeye başlamıyor bile. Unicode, daha büyük bir karakter repertuarından çok daha fazlasıdır; aynı zamanda bu karakterlerin hepsi birçok şekilde etkileşime girer.

(Bazıları) insanların istediklerini düşündükleri basit fikirli asgari önlemler bile, milyonlarca kod satırını, gösterişli yeni Cesur Yeni Dünya modernliğinize “yükseltme” şansı olmayan kodu feci şekilde kırmayı garanti ediyor .

İnsanların iddialarına göre çok daha karmaşık. Bunu son birkaç yıldır çok büyük, çok düşündüm. Yanlış olduğumu göstermeyi çok isterim. Ama olduğumu düşünmüyorum. Unicode temelde ona dayatmak istediğiniz modelden daha karmaşıktır ve burada halının altına asla süpüremeyeceğiniz karmaşıklık vardır. Eğer denerseniz, kendi kodunuzu ya da başka birinin kodunu kıracaksınız. Bir noktada, sadece yıkmak ve Unicode'un ne hakkında olduğunu öğrenmek zorundasınız. Öyle olmadığı gibi davranamazsınız.

🐪 Unicode'u şimdiye kadar kullandığım her şeyden çok daha kolay hale getirmek için kendi yolundan çıkıyor. Bunun kötü olduğunu düşünüyorsanız, bir süre başka bir şey deneyin. Sonra 🐪 ya geri dönün: ya daha iyi bir dünyaya döneceksin ya da seninle aynı bilgileri getireceksin, böylece bu şeyleri daha iyi hale getirmek için yeni bilgini kullanabiliriz.


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


En azından, 🐪 "varsayılan olarak Unicode'u etkinleştirmek" için gerekli görünen bazı şeyler şunlardır:

  1. Tüm kaynak kodları varsayılan olarak UTF-8'de olmalıdır. Sen o alabilirsiniz use utf8veya export PERL5OPTS=-Mutf8.

  2. 🐪 DATAtutamağı UTF-8 olmalıdır. Bunu, olduğu gibi, paket başına yapmak zorunda kalacaksınız binmode(DATA, ":encoding(UTF-8)").

  3. Komut dosyalarına program bağımsız değişkenlerinin varsayılan olarak UTF-8 olduğu anlaşılmalıdır. export PERL_UNICODE=A, veya perl -CA, veya export PERL5OPTS=-CA.

  4. Standart giriş, çıkış ve hata akışları varsayılan olarak UTF-8 olmalıdır. export PERL_UNICODE=Shepsi için, ya da I, Ove / veya Esadece bazıları için. Bu gibi perl -CS.

  5. 🐪 tarafından açılan diğer tutamaçlar aksi belirtilmedikçe UTF-8 olarak değerlendirilmelidir; export PERL_UNICODE=Dveya ive obu özel olanlar için; export PERL5OPTS=-CDçalışır. Bu -CSADonların hepsini yapar .

  6. Her iki üssü ve birlikte açtığınız tüm akışları kapsar export PERL5OPTS=-Mopen=:utf8,:std. Bakınız uniquote .

  7. UTF-8 kodlama hatalarını kaçırmak istemezsiniz. Deneyin export PERL5OPTS=-Mwarnings=FATAL,utf8. Ve giriş akışlarınızın sadece binmoded :encoding(UTF-8)değil , her zaman d olduğundan emin olun :utf8.

  8. 128-255 arasındaki kod noktalarının 🐪 ile anlaşılması gerekir ki, sadece doğrulanmamış ikili değerler değil, karşılık gelen Unicode kod noktalarıdır. use feature "unicode_strings"veya export PERL5OPTS=-Mfeature=unicode_strings. Bu yapacak uc("\xDF") eq "SS"ve "\xE9" =~ /\w/. Basit export PERL5OPTS=-Mv5.12veya daha iyisi de bunu elde edecektir.

  9. Adlandırılmış Unicode karakterler varsayılan olarak etkin değildir, bu nedenle ekleyin export PERL5OPTS=-Mcharnames=:full,:short,latin,greekveya benzerleri . Uninames ve tcgrep'e bakın .

  10. Hemen hemen her zaman standart Unicode::Normalizemodülün çeşitli dekompozisyon türlerinden işlevlere erişmeniz gerekir . export PERL5OPTS=-MUnicode::Normalize=NFD,NFKD,NFC,NFKDve ardından her zaman NFD üzerinden gelen ve NFC'den giden öğeleri çalıştırın. Bunlar için hiçbir I / O tabakası Farkında değilim, ama görüyoruz henüz yok nfc , NFD , NFKD ve NFKC .

  11. İçinde 🐪 dize karşılaştırmaları kullanarak eq, ne, lc, cmp, sort, c & cc & hep yanlış. Bunun yerine @a = sort @b, ihtiyacınız var @a = Unicode::Collate->new->sort(@b). Bunu da ekleyebilirsin export PERL5OPTS=-MUnicode::Collate. İkili karşılaştırmalar için anahtarı önbelleğe alabilirsiniz.

  12. İco yerleşik gibi Unicode veri gibi printfve writeyanlış bir şey yapmak. Sen kullanmak gerekir modülünü eski için ve bu da hem modül ikincisi için de. Bkz. Uwc ve unifmt .Unicode::GCStringUnicode::LineBreak

  13. Tamsayı olarak saymalarını istiyorsanız, \d+yakalamalarınızı işlev aracılığıyla çalıştırmanız gerekir ,Unicode::UCD::num çünkü 🐪'nin yerleşik atoi (3) şu anda yeterince akıllı değildir.

  14. 👽 dosya sistemlerinde dosya sistemi sorunlarınız olacak. Bazı dosya sistemleri sessizce NFC'ye dönüştürmeyi zorunlu kılar; diğerleri sessizce NFD'ye bir dönüşüm uygular. Ve diğerleri hala başka bir şey yapıyor. Bazıları konuyu tamamen görmezden gelir ve bu da daha büyük sorunlara yol açar. Bu yüzden aklı başında tutmak için kendi NFC / NFD kullanımınızı yapmanız gerekir.

  15. Tüm 🐪 kod içeren a-zveya A-Zve bu tür zorunluluk DEĞIŞTIRILMELIDIR dahil m//, s///ve tr///. Kodunuzun bozulduğu çığlık atan bir kırmızı bayrak olarak göze çarpmalıdır. Ancak nasıl değişmesi gerektiği açık değil. Doğru özellikleri elde etmek ve onların kasalarını anlamak düşündüğünüzden daha zordur. Kullandığım unichars ve uniprops her gün.

  16. Kullanan \p{Lu}kod, kullanılan kod kadar yanlıştır [A-Za-z]. Bunun \p{Upper}yerine kullanmanız ve nedenini bilmeniz gerekir. Evet, \p{Lowercase}ve \p{Lower}farklıdır \p{Ll}ve \p{Lowercase_Letter}.

  17. Kullanan kod [a-zA-Z]daha da kötüdür. Ve kullanamaz \pLveya \p{Letter}; kullanmak gerekiyor \p{Alphabetic}. Tüm alfabetikler harf değildir, bilirsiniz!

  18. 🐪 değişkenleri arıyorsanız /[\$\@\%]\w+/, bir sorununuz var demektir. Aramanız gerekiyor /[\$\@\%]\p{IDS}\p{IDC}*/ve bu noktalama işaretleri veya paket değişkenleri hakkında düşünmüyor bile.

  19. Boşluğu kontrol ediyorsanız , bağlı olarak \hve arasında seçim yapmalısınız \v. Ve asla kullanmamalısınız \s, çünkü yaygın inanışın aksine, ANLAM DEĞİL [\h\v] .

  20. Eğer kullanıyorsanız \nbir çizgi sınır için, hatta \r\n, o zaman yanlış yapıyoruz. Kullanmak zorundasın \R, ki bu aynı değil!

  21. Unicode :: Stringprep'i ne zaman arayacağınızı ve arayacağınızı bilmiyorsanız , öğrenmeniz daha iyi olur.

  22. Büyük / küçük harfe duyarlı olmayan karşılaştırmalar, aksanları ve benzerleri ne olursa olsun, iki şeyin aynı harfler olup olmadığını kontrol etmelidir. Bunu yapmanın en kolay yolu standart Unicode :: Collate modülüdür. Unicode::Collate->new(level => 1)->cmp($a, $b). Ayrıca eqyöntemler ve benzerleri vardır ve muhtemelen matchve substryöntemleri de öğrenmelisiniz . Bunlar 🐪 yerleşiklere göre belirgin avantajlara sahiptir.

  23. Bazen bu hala yeterli değildir ve bunun yerine Unicode :: Collate :: Locale modülüne ihtiyacınız vardır Unicode::Collate::Locale->new(locale => "de__phonebook", level => 1)->cmp($a, $b). Bunun Unicode::Collate::->new(level => 1)->eq("d", "ð")doğru olduğunu, ancak Unicode::Collate::Locale->new(locale=>"is",level => 1)->eq("d", " ð")yanlış olduğunu düşünün . Benzer şekilde, "ae" ve "æ" eqyerel ayarları kullanmıyorsanız veya İngilizce olanı kullanıyorsanız, ancak İzlanda yerel ayarında farklıysa. Şimdi ne olacak? Zor, söylüyorum. Bunlardan bazılarını test etmek için ucsort ile oynayabilirsiniz .

  24. Dize “in (consonsant, ünlü, ünsüz, ünlü) desen CVCV maç için nasıl düşünün niño ”. Daha iyi koyulaştırdığınız NFD formu, daha iyi koymuş olduğunuzu hatırladı - “nin \ x {303} o” olur. Şimdi ne yapacaksın? Bir sesli harf [aeiou](bu arada yanlış) gibi davranarak bile , böyle bir şey yapamazsınız (?=[aeiou])\X), çünkü NFD'de bile 'ø' gibi bir kod noktası ayrışmaz ! Ancak, size az önce gösterdiğim UCA karşılaştırmasını kullanarak bir 'o' değerine eşit olarak test edecektir. NFD'ye güvenemezsiniz, UCA'ya güvenmelisiniz.


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


Ve hepsi bu değil. İnsanların Unicode hakkında yaptığı bir milyon kırık varsayım var. Bu şeyleri anlayana kadar 🐪 kodları bozulacaktır.

  1. Kodlamanın bozuk olduğunu belirtmeden bir metin dosyasını açabileceğini varsayan kod.

  2. Varsayılan kodlamanın bir tür yerel platform kodlaması bozuk olduğunu varsayan kod bozulur.

  3. Japonca veya Çince web sayfalarının UTF ‑ 16'da UTF ‑ 8'den daha az yer kapladığını varsayan kod yanlıştır.

  4. Perl'in dahili olarak UTF ‑ 8 kullandığını varsayan kod yanlış.

  5. Kodlama hatalarının her zaman bir istisna oluşturacağını varsatan kod yanlıştır.

  6. Perl kod noktalarının 0x10_FFFF ile sınırlı olduğunu varsatan kod yanlış.

  7. $/Geçerli bir satır ayırıcıyla çalışacak bir şeye ayarlayabileceğinizi varsatan kod yanlış.

  8. Gibi casefolding üzerinde gidiş dönüş eşitliği varsayar Kod lc(uc($s)) eq $sveya uc(lc($s)) eq $stamamen kırılmış ve yanlış olduğunu. Düşünün o uc("σ")ve uc("ς") her ikisi de "Σ", ama lc("Σ")muhtemelen bunlardan ikisi döndüremez.

  9. Her küçük harf kod noktasının ayrı bir büyük harf olduğunu varsayarsak, ya da tam tersi bozuktur. Örneğin, "ª"büyük harf içermeyen bir küçük harftir; Her iki oysa "ᵃ"ve "ᴬ"harfler, ancak bunlar değil birer küçük harf; ancak, her ikisi de karşılık gelen büyük harf sürümleri olmayan küçük harf kod noktalarıdır. Anladım? Bunlar değil \p{Lowercase_Letter} ikisi olmasına rağmen \p{Letter}ve \p{Lowercase}.

  10. Büyük / küçük harf değişimi yapıldığını varsayan kod dizenin uzunluğunu değiştirmez.

  11. Sadece iki durumun bozulduğunu varsayan kod. Ayrıca titlecase var.

  12. Yalnızca harflerin büyük / küçük harf bozulduğunu varsatan kod. Sadece harflerin ötesinde, sayıların, sembollerin ve hatta işaretlerin büyük / küçük harfleri olduğu ortaya çıkıyor. Aslında, küçük harf değiştirme hatta gibi bir şey değişikliği ana genel kategori yapabilir \p{Mark}bir içine dönüm \p{Letter}. Ayrıca bir komut dosyasından diğerine geçmesini sağlayabilir.

  13. Büyük / küçük harf hiçbir zaman yerel ayara bağımlı olmadığını varsayan kod bozuktur.

  14. Unicode'un POSIX yerel ayarları hakkında bir incir verdiğini kabul eden kod bozuldu.

  15. Temel ASCII harflerini almak için aksanları kaldırabileceğinizi düşünen kod, kötü, yine de kırık, beyinden zarar görmüş, yanlış ve ölüm cezası için gerekçedir.

  16. Aksan \p{Diacritic}ve izlerin \p{Mark}aynı şey olduğunu kabul eden kod bozulur.

  17. Varsayılan kod , bozuk \p{GC=Dash_Punctuation}olduğu kadar kapsar \p{Dash}.

  18. Kısa çizgi, kısa çizgi ve eksilerin birbiriyle aynı olduğunu ya da her birinin yalnızca bir tanesinin olduğunu gösteren kod bozuk ve yanlıştır.

  19. Her kod noktasının birden fazla yazdırma sütunu kırılmadığını kabul eden kod bozulur.

  20. Tüm \p{Mark}karakterlerin sıfır yazdırma sütununu kapladığını varsayan kod bozuldu.

  21. Benziyorlar karakterler varsayar Kod vardır hem bozuldu.

  22. Kod do karakterler olduğunu varsayar değil benzemek olan değil aynı bozuldu.

  23. Yalnızca bir tanesinin \Xeşleşebileceği kod noktalarının sayısında bir sınır olduğu varsayılan kod yanlış.

  24. \XAsla bir \p{Mark}karakterle başlayamayacak olan kod yanlıştır.

  25. \XHiçbir zaman iki \p{Mark}karakter içermeyeceğini kabul eden kod yanlıştır.

  26. Kullanamayacağını varsatan kod "\x{FFFF}"yanlış.

  27. İki UTF-16 (vekil) kod birimi gerektiren BMP olmayan bir kod noktası varsayan kod, kod birimi başına bir tane olmak üzere iki ayrı UTF-8 karakterine kodlama yapar. Yapmaz: tek bir kod noktasına kodlar.

  28. Baştaki BOM'larla birlikte UTF ‐ 16 veya UTF ‐ 32'den kodlayan kod, sonuçta ortaya çıkan UTF-8'in başına bir BOM koyarsa bozulur. Bu o kadar aptal ki mühendisin göz kapaklarını çıkarması gerekiyor.

  29. CESU-8'in geçerli bir UTF kodlaması olduğunu varsayan kod yanlış. Benzer şekilde, "\xC0\x80"UTF-8 gibi U + 0000 kodlamasını düşünen kod bozuk ve yanlıştır. Bu çocuklar da göz kapağı tedavisini hak ediyor.

  30. >Her zaman sağa ve <her zaman sola doğru işaret eden karakterlerin yanlış olduğunu kabul eden kod yanlıştır, çünkü aslında bunu yapmazlar.

  31. Önce karakterin Xardından karakterlerin çıktısını alırsanız Y, bunların XYyanlış olarak görüneceğini kabul eden kod . Bazen bilmiyorlar.

  32. ASCII'nin İngilizceyi düzgün bir şekilde yazmak için yeterince iyi olduğunu kabul eden kod, aptal, dar görüşlü, okuma yazma bilmeyen, kırık, kötü ve yanlıştır. Başları kapalı! Bu çok aşırı görünüyorsa, uzlaşabiliriz: bundan sonra sadece bir ayaktan sadece ayak başparmağıyla yazabilirler. (Geri kalanlar bantlanmış olacaktır.)

  33. Tüm \p{Math}kod noktalarının görünür karakterler olduğunu kabul eden kod yanlış.

  34. \wYalnızca harf, rakam ve alt çizgi içerdiğini varsayan kod yanlış.

  35. Bunu varsayan ^ve ~noktalama işareti olan kod yanlış.

  36. üBir çıkış işareti olduğunu varsayan kod yanlış.

  37. İçlerinde herhangi bir harf bulunduğunu düşünen kod yanlış.

  38. İnanan kod, tamamen kırılmış \p{InLatin}olanla aynıdır \p{Latin}.

  39. \p{InLatin}Neredeyse faydalı olduğuna inanan kod neredeyse kesinlikle yanlıştır.

  40. $FIRST_LETTERBazı alfabelerde ilk harf $LAST_LETTERolarak ve aynı alfabede son harf olarak verilen [${FIRST_LETTER}-${LAST_LETTER}], herhangi bir anlamı olan inancın neredeyse her zaman kırılmış, yanlış ve anlamsız olduğuna inanan kod .

  41. Birisinin adının yalnızca belirli karakterleri içerebileceğine inanan kod aptalca, saldırgan ve yanlıştır.

  42. Unicode'u ASCII'ye indirmeye çalışan kodlar sadece yanlış olmakla kalmaz, failinin asla programlamada çalışmasına izin verilmemelidir. Dönemi. Tekrar görmelerine bile izin verilmeleri gerektiğinden bile olumlu değilim, çünkü şimdiye kadar onları çok iyi yapmadı.

  43. Textfile kodlamalarının var olmadığını iddia etmenin bir yolu olduğuna inanan kod bozuk ve tehlikelidir. Diğer gözü de düzeltebilir.

  44. Bilinmeyen karakterleri ?bozuk, aptalca, cesur hale dönüştüren ve YAPMAYIN! Neden olmasın RTFM.

  45. İşaretlenmemiş bir metin dosyasının kodlanmasını güvenilir bir şekilde tahmin edebileceğine inanan kod, Zeus'tan sadece bir şimşek çakacağının ölümcül bir koca ve naifé melanjından suçludur.

  46. printfUnicode verilerini doldurmak ve haklı göstermek için 🐪 genişliklerini kullanabileceğinize inanan kod bozuk ve yanlış.

  47. Belirli bir adla başarıyla bir dosya oluşturduktan sonra, onu lsya readdirda onu çevreleyen dizinde çalıştırdığınızda , oluşturduğunuz adın altında bu dosyayı buggy, kırık ve yanlış olduğunu göreceğinize inanan kod . Buna şaşırmayın!

  48. UTF-16'nın sabit genişlikli bir kodlama olduğuna inanan kod aptalca, bozuk ve yanlış. Programlama lisanslarını iptal edin.

  49. Bir düzlemdeki kod noktalarını diğer herhangi bir düzlemden farklı bir şekilde ele alan kod, ipso facto'nun kırık ve yanlış olmasıdır. Okula geri dön.

  50. Gibi şeylerin /s/isadece eşleşebileceğine "S"veya "s"bozuk ve yanlış olduğuna inanan kod . Şaşırdın.

  51. \PM\pM*Kullanmak yerine grafik kümelerini bulmak için kullanılan kod \Xbozuk ve yanlış.

  52. ASCII dünyasına geri dönmek isteyen insanlara bunu yürekten teşvik etmeli ve görkemli yükseltmelerinin onuruna, tüm veri giriş ihtiyaçları için elektrikli bir manuel daktilo ile ücretsiz olarak sağlanmalıdır . Onlara gönderilen mesajlar her satırda 40 karakter uzunluğunda bir telgrafla gönderilmeli ve bir kurye tarafından teslim edilmelidir. DUR.


😱 𝕾 𝖀 𝕸 𝕸 𝕬 𝕽 𝖄 😱


Yazdıklarımdan daha fazla “varsayılan Unicode in in” alabileceğinizi bilmiyorum. Eh, evet biliyorum: Kullanmakta gerektiğini Unicode::Collateve Unicode::LineBreakde. Ve muhtemelen daha fazlası.

Gördüğünüz gibi, gerçekten o kadar çok Unicode şey vardır do oraya için yaklaşık endişe zorunda hiç “Unicode için varsayılan” olarak böyle bir şey yok.

Keşfedeceğiniz şey, tıpkı 5.8'de yaptığımız gibi, tüm bunları baştan beri tasarlanmamış kodlara empoze etmenin imkansız olduğu. İyi niyetli bencilliğiniz tüm dünyayı kırdı.

Ve bir kez yaptıktan sonra bile, doğru olması için çok fazla düşünce gerektiren kritik sorunlar var. Çevirebileceğiniz bir anahtar yok. Burada beyin dışında hiçbir şey ve gerçek beyin demek yeterli değil. Öğrenmeniz gereken bir sürü şey var. Manuel daktiloya geri çekilme modulo, cehaletle gizlice girmeyi umamazsınız. Bu 21. yüzyıl ve Unicode'u kasıtlı cehaletten uzak tutamazsın.

Öğrenmelisin. Dönemi. “Her şey işe yarıyor” diye asla bu kadar kolay olmayacak, çünkü bu bir çok şeyin işe yaramadığını garanti edecek - bu da “hepsini işe yaratacak” bir yol olabileceği varsayımını geçersiz kılar.

Çok az ve çok sınırlı operasyonlar için birkaç makul varsayılan alabilirsiniz, ancak şeyleri düşündüğümden çok daha fazla düşünmeden.

Sadece bir örnek olarak, kanonik sıralama bazı gerçek baş ağrılarına neden olacaktır. 😭 "\x{F5}" 'õ' , "o\x{303}" 'õ' , "o\x{303}\x{304}" ' ȭ ' ve "o\x{304}\x{303}" 'ō̃' hepsi 'õ' ile eşleşmelidir , ancak dünyada bunu nasıl yapacaksınız? Bu göründüğünden daha zor, ancak hesaba katmanız gereken bir şey. 💣

Perl hakkında bildiğim bir şey varsa, Unicode bitlerinin yaptığı ve yapmadığı şeydir ve size söz veriyorum: “̲ᴛ̲ʜ̲ᴇ̲ʀ̲ᴇ̲ ̲ɪ̲s̲ ̲ɴ̲ᴏ̲ ̲U̲ɴ̲ɪ̲ᴄ̲ᴏ̲ᴅ̲ᴇ̲ ̲ᴍ̲ᴀ̲ɢ̲ɪ̲ᴄ̲ ̲ʙ̲ᴜ̲ʟ̲ʟ̲ᴇ̲ᴛ̲ ̲” 😞

Sadece bazı varsayılanları değiştiremez ve düzgün yelken açamazsınız. PERL_UNICODESet ayarlı olarak çalıştırdığım doğrudur "SA", ama hepsi bu ve hatta daha çok komut satırı şeyler içindir. Gerçek iş için, yukarıda belirtilen adımların hepsinden geçiyorum ve bunu çok, ** çok ** dikkatli bir şekilde yapıyorum.


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


56
Sherm Pendley'nin işaret ettiği gibi: "Hepsi!" Bugün yeni bir şey yazarsam, UTF-8 işleri halletmenin en kolay yolu olmalı . O değil. Isı yalıtım levhası bunu kanıtlar. Herkes bu kadar çok tumbler'ı doğru pozisyonlara çevirecek kadar bilgiye sahip değil. Üzgünüm, uzun ve zor bir gün geçirdim, bu yüzden yarın ana girişte örneklerle daha fazla yorum yapacağım.
wk

17
Bir sonuç yukarıdaki listeyi okumaktan açıkça anlaşılmalıdır: Vaka katlamayın. Sadece yapma. Hiç. Hesaplamalı olarak pahalı ve ne olursa olsun önemli olan semantik ile "yerel" tanımlamak için başarısız çalışır.
Tim Bray

72
Tchrist'in bu yazısının FF / Chrome / IE / Opera'da okunaksızlık noktasına kadar çılgınca farklı kıldığını ironik bulan tek kişi miyim?
damageboy

15
Genelde gönderiyi sevdim ve oy kullandığım halde, bir şey beni cehenneme çeviriyor. Bir çok "kod bozuk ..." var. İfadeyle tartışmasam da, kırılganlığı göstermek iyi olur. Bu yolla (cevabın bu kısmı) bir ranttan eğitime geçecektir.

36
@xenoterracide Hayır Kasıtlı olarak sorunlu kod noktaları kullanmadım; George Douros'un Unicode 6.0'ı kapsayan süper müthiş Symbola yazı tipini yüklemenizi sağlayan bir komplo . 😈 @depesz Her kırık varsayımın neden yanlış olduğunu açıklayacak yer yok. @leonbloy Bunların çoğu ve çoğu , sadece Perl için değil, genel olarak Unicode için geçerlidir. Bu materyalden bazıları Ekim ayında çıkacak olan 4. Programlama Perl 4th 'de gösterilebilir . 🎃 Üzerinde çalışmak için bir ayım kaldı ve Unicode orada;; regexes de
tchrist

96

Unicode metni işlemek için iki aşama vardır. Birincisi "bilgiyi kaybetmeden nasıl girebilir ve çıktısını alabilirim" dir. İkincisi, "yerel dil kurallarına göre metni nasıl ele alırım" dır.

tchrist'in yazısı her ikisini de kapsar, ancak ikinci bölüm, yazısındaki metnin% 99'unun geldiği yerdir. Çoğu program G / Ç'yi doğru işlemez, bu nedenle normalleştirme ve harmanlama konusunda endişelenmeye başlamadan önce bunu anlamak önemlidir.

Bu yazı ilk sorunu çözmeyi amaçlıyor

Perl'e veri okuduğunuzda, kodlamanın ne olduğu umurumda değil. Biraz bellek ayırır ve baytları orada saklar. Eğer söylerseniz print $str, bu baytları terminalinize böler, bu da muhtemelen ona yazılan her şeyin UTF-8 olduğunu varsayar ve metniniz görünür.

Harikulade.

Dışında, değil. Verilere metin olarak davranmaya çalışırsanız Kötü Bir Şey olduğunu göreceksiniz. Sen öteye gitmek gerek lengthdizenizle ne hakkında Perl dizenizle düşünür ve ne düşünmek katılmıyorum olduğunu görmek. Gibi bir astar yazın: perl -E 'while(<>){ chomp; say length }'yazın 文字化けve 12 ... doğru cevabı değil, 4.

Çünkü Perl, dizenizin metin olmadığını varsayar. Size doğru cevabı vermeden önce metin olduğunu söylemelisiniz.

Bu yeterince kolay; Kodlama modülünün bunu yapacak işlevleri vardır. Genel giriş noktası Encode::decode(veya use Encode qw(decode)elbette). Bu işlev dış dünyadan bir dizi alır ("8-bit bayt" demenin bir yolu olan "sekizli" olarak adlandıracağız) ve Perl'in anlayacağı bir metne dönüştürür. İlk argüman, "UTF-8" veya "ASCII" veya "EUC-JP" gibi bir karakter kodlama adıdır. İkinci argüman dizedir. Dönüş değeri, metni içeren Perl skaleridir.

(Ayrıca Encode::decode_utf8kodlama için UTF-8 olduğunu varsayar.)

Tek astarımızı yeniden yazarsak:

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

Biz 文字 化 け yazıp sonuç olarak "4" alırız. Başarı.

Bu, Perl'deki Unicode sorunlarının% 99'una çözüm.

Anahtar, programınıza herhangi bir metin geldiğinde, kodunu çözmeniz gerekir. İnternet karakter iletemez. Dosyalar karakterleri depolayamaz. Veritabanınızda karakter yok. Sadece sekizlileri vardır ve sekizlilere Perl'de karakter olarak davranamazsınız. Kodlama modülüyle kodlanmış sekizlileri Perl karakterlerine deşifre etmelisiniz.

Sorunun diğer yarısı, programınızdan veri almaktır. Bunu yapmak kolaydır; sadece use Encode qw(encode), verilerinizin kodlanmasının ne olacağına karar verin (UTF-8, UTF-8'i anlayan terminallere, Windows'taki dosyalar için UTF-16 vb.) ve sonra çıktı almak encode($encoding, $data)yerine sonucunu çıktılayın $data.

Bu işlem, Perl'in programınızın üzerinde çalıştığı karakterlerini dış dünya tarafından kullanılabilecek sekizlilere dönüştürür. İnternet üzerinden veya terminallerimize sadece karakter gönderebilmemiz çok daha kolay olurdu, ancak yapamayız: sadece sekizli. Bu yüzden karakterleri sekizlilere dönüştürmeliyiz, aksi takdirde sonuçlar tanımsızdır.

Özetlemek gerekirse: tüm çıkışları kodlayın ve tüm girişlerin kodunu çözün.

Şimdi bunu biraz zorlaştıran üç konu hakkında konuşacağız. Birincisi kütüphaneler. Metni doğru kullanıyorlar mı? Cevap ... deniyorlar. Bir web sayfası indirirseniz, LWP sonucunuzu metin olarak geri verecektir. Sonuçta doğru yöntemi çağırırsanız, bu (ve öyle decoded_contentdeğil content, sadece sunucudan aldığı sekizli akıştır). Veritabanı sürücüleri kesintili olabilir; DBD :: SQLite'ı sadece Perl ile kullanırsanız, işe yarayacaktır, ancak başka bir araç veritabanınızda UTF-8 dışında bir kodlama olarak depolanan metni koyduysa ... iyi ... doğru şekilde işlenmeyecek doğru işlemek için kod yazana kadar.

Verilerin çıktısını almak genellikle daha kolaydır, ancak "baskıda geniş karakter" görürseniz kodlamayı bir yere karıştırdığınızı bilirsiniz. Bu uyarı "hey, Perl karakterlerini dış dünyaya sızdırmaya çalışıyorsun ve bu hiç mantıklı değil" anlamına geliyor. Programınız çalışıyor gibi görünüyor (çünkü diğer uç genellikle ham Perl karakterlerini doğru bir şekilde işliyor), ancak çok bozuk ve her an çalışmayı durdurabilir. Açık bir şekilde düzeltin Encode::encode!

İkinci sorun UTF-8 kodlu kaynak kodudur. use utf8Her dosyanın üstünde söylemediğiniz sürece , Perl kaynak kodunuzun UTF-8 olduğunu varsaymaz. Bu, her seferinde bir şey söylediğinizde my $var = 'ほげ', programınıza her şeyi korkunç bir şekilde kıracak çöp enjekte ettiğiniz anlamına gelir . Sen "kullanım utf8" gerekmez, ama bilmiyorsun, sen gerekir programınızda herhangi ASCII olmayan karakterleri kullanmayın.

Üçüncü sorun, Perl'in Geçmiş'i nasıl ele aldığıdır. Uzun zaman önce, Unicode diye bir şey yoktu ve Perl her şeyin Latin-1 metin veya ikili olduğunu varsaydı. Veriler programınıza girdiğinde ve metin olarak ele almaya başladığınızda, Perl her sekizliyi bir Latin-1 karakteri olarak ele alır. Bu yüzden, "文字 化 け" uzunluğunu sorduğumuzda, 12 tane aldık. Perl, Latin-1 dizesi "æååã" (bazıları yazdırılamayan 12 karakter) üzerinde çalıştığımızı varsaydı.

Buna "örtük yükseltme" denir ve bunu yapmak oldukça makul bir şeydir, ancak metniniz Latin-1 değilse istediğiniz şey değildir. Bu yüzden girdinin kodunu açıkça çözmek önemlidir: Bunu yapmazsanız, Perl yapar ve yanlış yapabilir.

İnsanlar, verilerinin yarısının uygun bir karakter dizesi olduğu ve bazılarının hala ikili olduğu durumlarda sorun yaşarlar. Perl, hala ikili olan kısmı Latin-1 metni gibi yorumlayacak ve daha sonra doğru karakter verileriyle birleştirecektir. Bu, karakterlerinizi doğru bir şekilde programınızı kırmış gibi gösterecektir, ancak gerçekte, yeterince düzeltmediniz.

İşte bir örnek: UTF-8 kodlu metin dosyasını okuyan bir programınız var, PILE OF POOher satıra bir Unicode takıyorsunuz ve yazdırıyorsunuz. Sen şöyle yaz:

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

Ardından, UTF-8 ile kodlanmış bazı veriler üzerinde çalıştırın:

perl poo.pl input-data.txt

UTF-8 verilerini her satırın sonunda bir kaka ile yazdırır. Mükemmel, programım çalışıyor!

Ama hayır, sadece ikili birleştirme yapıyorsun. Dosyadan sekizli okuyorsunuz, bir \nchomp ile a'yı kaldırıyorsunuz ve daha sonra PILE OF POOkarakterin UTF-8 temsilindeki baytlara yapışıyorsunuz . Programınızı verileri dosyadan kodunu çözmek ve çıktıyı kodlamak için gözden geçirdiğinizde, kaka yerine çöp aldığınızı ("ð ©") fark edeceksiniz. Bu, giriş dosyasının kodunun çözülmesinin yanlış bir şey olduğuna inanmanıza neden olacaktır. Değil.

Sorun şu ki, kaka örtük olarak latin-1 olarak yükseltiliyor. Eğer varsa use utf8ikili yerine edebi metin yapmak, o zaman tekrar çalışacaktır!

(Bu, Unicode'lu insanlara yardım ederken gördüğüm bir numaralı problem. Haklıydılar ve programlarını bozdular. Tanımlanmamış sonuçlar için üzücü olan bu: Uzun süre çalışan bir programa sahip olabilirsiniz, ancak onarmaya başladığınızda, Endişelenmeyin; programınıza kodlama / kod çözme ifadeleri ekliyorsanız ve kırılırsa, sadece daha fazla işiniz olduğu anlamına gelir.Bir dahaki sefere, Unicode'u akılda tutarak tasarım yaptığınızda, daha kolay!)

Perl ve Unicode hakkında bilmeniz gereken her şey bu. Perl'e verilerinizin ne olduğunu söylerseniz, tüm popüler programlama dilleri arasında en iyi Unicode desteğine sahiptir. Ne tür bir metni beslediğinizi sihirli bir şekilde bileceğini varsayarsanız, verilerinizi geri dönülmez bir şekilde çöpe atacaksınız. Programınızın bugün UTF-8 terminalinizde çalışması, yarının UTF-16 kodlu bir dosyada çalışacağı anlamına gelmez. Şimdi güvenli hale getirin ve kullanıcılarınızın verilerini çöpe atmanın baş ağrısından kurtulun!

Unicode'un işlenmesinin kolay kısmı çıktıyı ve kod çözme girişini kodlamaktır. Zor kısım, tüm giriş ve çıkışlarınızı bulmak ve hangi kodlamayı olduğunu belirlemektir. Ama bu yüzden büyük paralar alıyorsunuz :)


İlke iyi açıklanmıştır, ancak I / O için pratik yaklaşım eksiktir. Açıkça Encodemodülü kullanmak sıkıcı ve hataya açıktır ve G / Ç ile ilgili kodu okumayı gerçekten acı verici hale getirir. G / Ç katmanları, gerektiğinde şeffaf bir şekilde kodladıkları ve kod çözdükleri için bir çözüm sağlar. openve binmodeşartnamelerine izin verin ve pragma open, tchrist'in cevabında önerdiği gibi varsayılanları belirler.
Palec

48

Hepimiz bunun birçok nedenden dolayı zor bir sorun olduğu konusunda hemfikiriz, ancak herkes için daha kolay hale getirmeye çalışmanın tam nedeni budur.

CPAN, utf8 :: all üzerinde "Unicode'u açmaya çalışan yeni bir modül var . Hepsi".

Belirtildiği gibi, tüm sistemi (dış programlar, harici web istekleri, vb.) Sihirli olarak Unicode'u kullanamazsınız, ancak ortak sorunları daha kolay hale getiren mantıklı araçları yapmak için birlikte çalışabiliriz. Programcı olmamızın nedeni budur.

Utf8 :: hepsi olması gerektiğini düşündüğünüz bir şey yapmazsa, daha iyi hale getirmek için onu geliştirelim. Ya da birlikte insanların değişen ihtiyaçlarına olabildiğince uygun ek araçlar yapalım.

'


5
Belirtilen modülde iyileştirme için çok yer görüyorum utf8::all. unicode_stringsF before ᴀɴᴅ ᴀᴛ Lᴏɴɢ Lᴀsᴛ'nin regexes'i onlarla sabitlemek için düzelttiği özellikten önce yazılmıştır /u. Hataları kodlama konusunda bir istisna yarattığına inanmıyorum ve bu gerçekten sahip olmanız gereken bir şey. Henüz yüklenmemiş use charnames ":full"olan pragmada yüklenmez. O üzerinde uyarmaz [a-z]ve bu tür, printfkullanarak, dize genişlikleri \nyerine \Rve .yerine \X, ama belki those're daha bir Perl::Criticmesele. Eğer ben olsaydım, içeri ve dışarı eklerdim.
tchrist

13
@tchrist utf8 :: all için sorun izleyici burada. github.com/doherty/utf8-all/issues Önerilerinizi duymak isterler .
Schwern

4
@Schwern: writtens, ama burada yazdıklarımdan çalmaktan ve sıkıştırmaktan çekinmeyin. Dürüst olmak gerekirse, hâlâ neler yapılabileceği ve nerede yapılması gerektiği konusunda neler yapabileceğimi hissediyorum. İşte sıralama boşaltma kapalı güzel örnek: unichars -gs '/(?=\P{Ll})\p{Lower}|(?=\P{Lu})\p{Upper}/x' | ucsort --upper | cat -n | less -r. Benzer şekilde, küçük önişleme adımları ... | ucsort --upper --preprocess='s/(\d+)/sprintf "%#012d", $1/ge'da gerçekten güzel olabilir ve başkalarının kararlarını onlar için vermek istemem. Hala Unicode araç kutumu yapıyorum .
tchrist

35

Bence Unicode'u ve onun Perl ile olan ilişkisini yanlış anlıyorsun. Verilerinizi, Unicode, ISO-8859-1 veya diğer pek çok şeyi nasıl saklarsanız saklayın programınız, aldığı baytları girdi (kod çözme) olarak nasıl yorumlayacağını ve çıktısını almak istediği bilgiyi (kodlama) nasıl temsil edeceğini bilmelidir. ). Bu yorumu yanlış yaparsanız verileri bozarsınız. Programınızın içinde, programınızın dışındaki öğelere nasıl davranacağınızı söyleyecek sihirli bir varsayılan kurulum yoktur.

Büyük olasılıkla zor olduğunu düşünüyorsunuz çünkü ASCII olan her şeye alışkınız. Düşünmeniz gereken her şey programlama dili ve etkileşimde bulunması gereken tüm şeyler tarafından göz ardı edildi. Her şey UTF-8'den başka bir şey kullanmamışsa ve başka seçeneğiniz olmasaydı, UTF-8 de o kadar kolay olurdu. Ancak her şey UTF-8 kullanmaz. Örneğin, giriş tutamacınızın gerçekte olmadıkça UTF-8 oktet aldığını düşünmesini istemezsiniz ve onlardan okunan şey UTF-8'i işleyebiliyorsa çıktı tutamaçlarınızın UTF-8 olmasını istemezsiniz. . Perl'in bunları bilmesinin bir yolu yok. Bu yüzden programcısın.

Perl 5'te Unicode'un çok karmaşık olduğunu düşünmüyorum. Bence korkutucu ve insanlar bundan kaçınıyor. Bir fark var. Bu amaçla, Unicode'u Öğrenme Perl, 6. Baskı'ya koydum ve Etkili Perl Programlama'da birçok Unicode öğesi var . Unicode'u ve nasıl çalıştığını öğrenmek ve anlamak için zaman harcamanız gerekir. Aksi halde etkili bir şekilde kullanamazsınız.


3
Bence bir fikrin var: korkutucu. Olmalı mı? Benim için Unicode nimet, Perl5'te kullanmak değil (ASCII olarak bir şey olduğunu sanmıyorum, ana dilimin en azından iso8859-4'e ihtiyacı var). Rakudo'yu kurdum ve UTF-8 ile denediğim her şey (bu sınırlı sanal alanda) kutunun dışında çalıştı. Bir şey mi kaçırdım? Tekrar vurgularım: İnce ayarlanmış Unicode desteğine sahip olmak iyidir, ancak çoğu zaman buna gerek yoktur. Konudan korkmak için bir yol, içselleri anlamak için herkesin çok şey okumasıdır. Diğer: Özel pragmalarımız var, bu use utf8_everywhereyüzden insanları mutlu ediyor. Neden sonuncu olmasın?
wk

3
Hala noktayı kaçırdığını düşünüyorum. Ne işe yaradı? İçselleri anlamanız gerekmez. Bunu anlamak için gereken Externals farklı kodlamalar ve aynı karakterlerin farklı değerlere sahiptirler dizeleri işlemek istiyorum nasıl ve. Tom'un tavsiyesini tekrar okuyun. Bahse girerim, Rakudo'nun sizin için uygun olmadığını göreceksiniz.
brian d foy

1
@wk: Randy'nin cevabını tekrar oku. Size zaten sınırlamaların ne olduğunu söylemişti.
brian d foy

2
@brian d foy: bu sınırlamanın iyi olduğunu düşünüyorum, tchrist'in dediği gibi, her yön için sihirli mermi yok (itiraf ediyorum: bu soruyu burada sormadan önce çoğunu görmedim). Bu nedenle, utf8 :: all gibi bir çok temel şeyi kapsadığımızda, herkesin sadece utf8 kullanımıyla ilgili temel bilgileri almak için kendi büyük kazan plakasını oluşturmasına gerek yoktur. "Hiç korku yok" demek istediğimde: herkes projelerine, temel bilgilerin ele alındığını bilerek başlayabilir. Evet, haklısın, hala çok fazla sorun var. Ancak başlamak daha kolay olduğunda, bunları çözmek için daha fazla insanımız olacak. IMHO
wk

1
@wk - "utf8: all" veya "uni :: perl ile tek" yanlış "sadece bir - CORE'da değiller - bu yüzden herkes onu CPAN'dan yüklemelidir. Ve bunun büyük olmadığını düşünürseniz anlaşma - yeniden düşünün lütfen - evet, yardımcı bir modül ile utf8 kullanmak daha kolay.Onsuz, CORE perl hala unicode desteği var - ama çok çok karmaşık.Ve bu yanlış.
jm666

28

Bu konuyu okurken, insanların " UTF-8 " i " Unicode " ile eşanlamlı olarak kullandıkları izlenimini edindim . Lütfen Unicode'un ASCII kodunun genişletilmiş akrabası olan "Kod Noktaları" ile Unicode'un çeşitli "kodlamaları" arasında bir ayrım yapın. UTF-8, UTF-16 ve UTF-32 mevcut olan ve birkaçı eski olan birkaç tanesi var.

Lütfen UTF-8 (ve diğer tüm kodlamalar ) mevcuttur ve yalnızca girdi veya çıktı anlamında anlam taşırlar. Dahili olarak, Perl 5.8.1'den bu yana, tüm dizeler Unicode "Kod noktaları" olarak tutulur. Doğru, daha önce hayranlıkla kapsanan bazı özellikleri etkinleştirmeniz gerekiyor.


19
İnsanların Uɴɪᴄᴏᴅᴇ'yi UTF-8⧸16⧸32 ile çok sık karıştırdıklarına katılıyorum, ancak U but'nin ᴀsᴄɪɪ'ye göre sadece genişletilmiş bir karakter seti olduğu temelde ve eleştirel olarak doğru değil . En fazla, bu sadece 64sᴏ ‑ 10646'dan başka bir şey değildir . Uɴɪᴄᴏᴅᴇ çok daha fazlasını içerir : harmanlama, büyük / küçük harf dağılımı, normalleştirme formları, grafik kümeleri, kelime ve satır sonu, komut dosyaları, sayısal eşdeğerler, genişlikler, çift yönlülük, glif varyantları, bağlamsal davranış, yerel ayarlar, normal ifadeler, sınıfları birleştirme, 100'lerin özellikleri ve çok daha fazlası t
tchrist

15
@tchrist: ilk adım, verileri çöpe atmadan programınıza ve dış dünyaya aktarmaktır. o zaman harmanlama, vaka katlama, glif varyantları, vb.
jrockway

7
Katılıyorum, giriş veya çıkış çöp kutusuna perl almak ilk öncelik olmalıdır. İstediğim şu hayali konuşmayı somutlaştırabilecek bir modül veya pragmaya sahip olmaktı: "- Sevgili Perl. Bu program için, tüm girdi ve çıktılar sadece UTF-8 olacak. Verilerimi çöpe atamaz mısınız? - Yani sadece UFT-8 diyorsun, emin misin? - Evet - Gerçekten, gerçekten emin misin? - Tamam ozaman."
hlovdal

10

Vahşi doğada, çoğunlukla ortak CPAN modülleri biçiminde gerçekten korkunç miktarda eski kod var. Etkilenebilecek harici modüller kullanırsam Unicode'u etkinleştirirken oldukça dikkatli olmalıyım ve düzenli olarak kullandığım birkaç Perl komut dosyasında bazı Unicode ile ilgili hataları tanımlamaya ve düzeltmeye çalışıyorum (özellikle, iTiVo başarısız oluyor) kod dönüştürme sorunları nedeniyle 7 bit ASCII olmayan herhangi bir şey için kötü).


-CPerl'i Unicode-wise ile aynı sayfada olduğundan emin olmak için seçeneği kullanmak istedim, çünkü açıkça ayarlı $LANGve $LC_ALLdüzgün bir şekilde ayarlasam da Unicode yerine ISO 8859/1 kullanmaya karar verdim . (Bu aslında platform yerel kütüphanelerindeki hataları yansıtabilir.) Ne olursa olsun, işi yapan Perl betikleri dönüştürme hatalarıyla düştüğü için iTivo'yu aksanlı programlarda kullanamam çok can sıkıcı oldu.
geekosaur

3
-CSeçenekleri olmayan bir yalnız adamcağız ve hataya açıktır . Sen dünyayı kırıyorsun. PERL5OPTDeğişken olarak ayarlayın ve -Cne demek istediğimi göreceksiniz. V5.8'de bu şekilde denedik ve bu bir felaketti. Beklemeyen programlara şimdi Unicode ile ilgilenip ilgilenmediklerini söyleyemezsiniz ve söylememelisiniz. Güvenlik sorunları da var. En azından, print while <>ikili veri geçilirse herhangi bir şey kırılacaktır. Tüm veritabanı kodu da öyle. Bu korkunç bir fikir.
tchrist

1
Aslında -Cseçenekler olmadan genel olarak konuşuyordum . Üzerinde çalıştığım özel çağrı şuydu -CSDA. Bununla birlikte, uzun bir süre 5.8.x ile sıkıştım (merhaba MacPorts ...), bu yüzden belki de bir parçasıydı.
geekosaur

1
PERL_UNICODE SA olarak ayarlanmış olarak çalıştırın. Sen CAN NOT D'ye ayarlayın
tchrist

@tchrist: Bazı Perl varmint -CSDA ve PERL_UNICODE = SDA kullanımını gösteren kod yayınlıyor . Lütfen topluluktaki etkinizi kullanın. Durdurulmalı!
Ashley

1

Unicode dizeleri özelliğini etkinleştirmelisiniz ve v5.14 kullanıyorsanız bu varsayılan değerdir;

Gerçekten unicode tanımlayıcıları esp kullanmamalısınız. perl5'te güvensiz oldukları için utf8 üzerinden yabancı kod için, sadece cperl bu hakkı elde etti. Bkz. Örneğin http://perl11.org/blog/unicode-identifiers.html

Dosya tanıtıcılarınız / akışlarınız için utf8 ile ilgili olarak: Harici verilerinizin kodlanmasına kendiniz karar vermeniz gerekir. Bir kütüphane bunu bilemez ve libc bile utf8'i desteklemediğinden, uygun utf8 verisi nadirdir. Daha fazla wtf8 var, etrafta utf8'in pencere sapması var.

BTW: Moose gerçekten "Modern Perl" değil, sadece ismi kaçırdılar. Moose mükemmel Larry Wall tarzı postmodern perl Bjarne Stroustrup tarzı ile karıştırılmış her şey, uygun perl6 sözdiziminin eklektik bir sapması ile, örneğin değişken isimler için dizeleri kullanmak, korkunç alanlar sözdizimi ve çok olgunlaşmamış naif bir uygulama ile uygun uygulama. cperl ve perl6, formun işlevi izlediği ve uygulamanın azaltıldığı ve optimize edildiği gerçek modern perlslerdir.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.