Dlaczego współczesny Perl domyślnie unika UTF-8?


557

Zastanawiam się, dlaczego większość nowoczesnych rozwiązań zbudowanych przy użyciu Perla domyślnie nie włącza UTF-8 .

Rozumiem, że istnieje wiele starszych problemów dla podstawowych skryptów Perla, w których może to popsuć. Jednak z mojego punktu widzenia w XXI wieku duże nowe projekty (lub projekty z dużą perspektywą) powinny sprawić, by ich oprogramowanie UTF-8 było od podstaw odporne. Nadal nie widzę, żeby to się działo. Na przykład Łoś włącza surowe i ostrzeżenia, ale nie Unicode . Modern :: Perl redukuje również płytę kotłową, ale nie obsługuje UTF-8.

Dlaczego? Czy istnieją jakieś powody, aby unikać UTF-8 w nowoczesnych projektach Perla w 2011 roku?


Komentowanie @tchrist stało się zbyt długie, więc dodaję to tutaj.

Wygląda na to, że nie wyraziłem się jasno. Pozwól mi spróbować dodać kilka rzeczy.

tchrist i ja widzimy sytuację dość podobnie, ale nasze wnioski są całkowicie przeciwne. Zgadzam się, sytuacja w Unicode jest skomplikowana, ale dlatego my (użytkownicy Perla i kodery) potrzebujemy warstwy (lub pragmy), która sprawia, że ​​obsługa UTF-8 jest tak łatwa, jak musi być teraz.

tchrist wskazał na wiele aspektów do omówienia, będę czytać i myśleć o nich przez kilka dni, a nawet tygodni. Jednak nie o to mi chodzi. tchrist próbuje udowodnić, że nie ma jednego sposobu „włączenia UTF-8”. Nie mam zbyt dużej wiedzy, aby się z tym kłócić. Trzymam się więc przykładów na żywo.

Grałem z Rakudo, a UTF-8 był tam, gdzie potrzebowałem . Nie miałem żadnych problemów, po prostu działało. Może są jakieś ograniczenia gdzieś głębiej, ale na początku wszystko, co testowałem, działało zgodnie z oczekiwaniami.

Czy nie powinien to być również cel w nowoczesnym Perlu 5? Podkreślam to bardziej: nie sugeruję UTF-8 jako domyślnego zestawu znaków dla podstawowego Perla, sugeruję możliwość uruchomienia go za pomocą przystawki dla tych, którzy opracowują nowe projekty.

Kolejny przykład, ale z bardziej negatywnym tonem. Ramy powinny ułatwić rozwój. Kilka lat temu próbowałem frameworków internetowych, ale po prostu je wyrzuciłem, ponieważ „włączenie UTF-8” było tak niejasne. Nie znalazłem jak i gdzie podpiąć obsługę Unicode. To było tak czasochłonne, że łatwiej mi było pójść starą drogą. Teraz widziałem tutaj, że istnieje nagroda za rozwiązanie tego samego problemu z Masonem 2: Jak sprawić, by Mason2 UTF-8 był czysty? . Jest to więc całkiem nowy framework, ale używanie go z UTF-8 wymaga głębokiej znajomości jego wewnętrznych elementów. To jest jak duży czerwony znak: STOP, nie używaj mnie!

Naprawdę lubię Perla. Ale radzenie sobie z Unicode jest bolesne. Nadal czuję, że biegnę po ścianach. W pewien sposób tchrist ma rację i odpowiada na moje pytania: nowe projekty nie przyciągają UTF-8, ponieważ jest to zbyt skomplikowane w Perlu 5.


15
Przykro mi, ale zgadzam się z @tchrist - UTF-8 jest niezwykle trudny. Nie ma frameworka ani narzędzia, które po prostu „przerzuca przełącznik”, a następnie obsługuje go poprawnie. Jest to coś, o czym musisz pomyśleć bezpośrednio przy projektowaniu aplikacji - nie jest to coś, co może poradzić sobie jakikolwiek framework lub język. Jeśli rakudo właśnie dla ciebie zadziałało, nie byłeś wystarczająco ryzykowny ze swoimi przypadkami testowymi - ponieważ zajmie to kilka przykładów z odpowiedzi @ tchrist i rzeźnika.
Billy ONeal

12
Co dokładnie masz nadzieję, że zrobią Moose lub Modern :: Perl? Magiczne przekształcanie losowo kodowanych danych znakowych w plikach i bazach danych w poprawne dane?
jrockway

13
Co to znaczy? Łoś nie ma nic wspólnego z manipulowaniem tekstem. Dlaczego miałby wiedzieć o kodowaniu znaków, a tym bardziej wybrać domyślny kodowanie? (W każdym razie powodem, dla którego wymienione przez ciebie pragmy nie dotykają kodowania, jest to, że konwencja ma wpływ na pragmaty Perla na zachowanie leksykalne . Zakładanie, że cały świat, wraz z innymi modułami, to UTF-8, jest po prostu niewłaściwą rzeczą do zrobienia , To nie jest PHP ani Ruby.)
jrockway

8
(Również ... „najnowocześniejszych Perl apps” przerwa na UTF-8 Ja na pewno nigdy napisany wniosek, Perl czy inaczej, to nie jest Unicode czyste?).
jrockway

11
Uwaga tchrist (Tom Christiansen) opublikował swoje [ training.perl.com/OSCON2011/index.html Materiały Toma Christiansena dla OSCON 2011] na temat Unicode. Ten zatytułowany „Strzelanie do obsługi Unicode: dobry, zły i (głównie) brzydki” mówi o wsparciu Unicode w różnych językach programowania. Tylko Google Go i Perl5 obsługuje pełną wersję Unicode, tylko wbudowane Google Go (bez wzmianki o Perl6).
Jakub Narębski

Odpowiedzi:


1146

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

  1. Ustaw swoją PERL_UNICODEzmienną na AS. To powoduje, że wszystkie skrypty Perla dekodują @ARGVjako ciągi UTF ‑ 8, i ustawia kodowanie wszystkich trzech stdin, stdout i stderr na UTF ‑ 8. Oba są efektami globalnymi, a nie leksykalnymi.

  2. W górnej części pliku źródłowego (program, moduł, biblioteka, dohickey) wyraźnie zaznacz, że korzystasz z Perla w wersji 5.12 lub nowszej poprzez:

    use v5.12;  # minimal for unicode string feature
    use v5.14;  # optimal for unicode string feature
  3. Włącz ostrzeżenia, ponieważ poprzednia deklaracja włącza tylko ograniczenia i funkcje, a nie ostrzeżenia. Sugeruję również promowanie ostrzeżeń Unicode w wyjątki, więc używaj obu tych linii, a nie tylko jednej. Uwaga jednak, że pod v5.14 The utf8klasa ostrzeżenie obejmuje trzy inne subwarnings które mogą być osobno włączone: nonchar, surrogate, i non_unicode. Te możesz chcieć mieć większą kontrolę.

    use warnings;
    use warnings qw( FATAL utf8 );
  4. Oświadcz, że ta jednostka źródłowa jest zakodowana jako UTF ‑ 8. Chociaż kiedyś ta pragma robiła inne rzeczy, teraz służy tylko temu jednemu celowi i żadnemu innemu:

    use utf8;
  5. Zadeklaruj, że wszystko, co otwiera uchwyt pliku w tym zakresie leksykalnym, ale nie gdzie indziej, zakłada, że ​​ten strumień jest zakodowany w UTF-8, chyba że powiesz inaczej. W ten sposób nie wpływasz na kod innego modułu lub innego programu.

    use open qw( :encoding(UTF-8) :std );
  6. Włącz nazwane znaki przez \N{CHARNAME}.

    use charnames qw( :full :short );
  7. Jeśli masz DATAuchwyt, musisz jawnie ustawić jego kodowanie. Jeśli chcesz, aby to był UTF ‑ 8, powiedz:

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

Oczywiście nie ma końca innymi sprawami, którymi możesz się w końcu zająć, ale wystarczą one do przybliżenia celu państwa, jakim jest „sprawienie, by wszystko działało tylko z UTF ‑ 8”, choć dla nieco osłabionego rozumienia tych terminów.

Jeszcze jedna pragma, choć nie jest związana z Unicode, to:

      use autodie;

Jest to zdecydowanie zalecane.

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


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


Moja własna płyta dziś wygląda tak:

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__

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


Mówiąc, że „Perl powinien [ jakoś! ] włącz Unicode domyślnie ”nawet nie zaczyna myśleć o tym, aby powiedzieć wystarczająco dużo, aby być nawet marginalnie przydatnym w jakimś rzadkim i odosobnionym przypadku. Unicode to znacznie więcej niż tylko większy repertuar postaci; to także sposób, w jaki wszystkie te postacie oddziałują na wiele, wiele sposobów.

Nawet proste, minimalne miary, które (niektórzy) ludzie myślą, że chcą, nieszczęśliwie łamią miliony linii kodu, kodu, który nie ma szansy na „uaktualnienie” do nowej, wspaniałej nowoczesności Brave New World .

Jest to o wiele bardziej skomplikowane niż ludzie udają. Przez ostatnie kilka lat myślałem o tym bardzo dużo. Chciałbym pokazać, że się mylę. Ale nie wydaje mi się. Unicode jest zasadniczo bardziej złożony niż model, który chciałbyś na niego nałożyć, a tutaj jest złożoność, której nigdy nie można zamiatać pod dywan. Jeśli spróbujesz, złamiesz swój własny kod lub kod innej osoby. W pewnym momencie musisz po prostu się zepsuć i dowiedzieć się, o co chodzi w Unicode. Nie możesz udawać, że to coś, czym nie jest.

🐪 robi wszystko, aby Unicode był łatwy, znacznie bardziej niż cokolwiek innego, z czego kiedykolwiek korzystałem. Jeśli uważasz, że to źle, spróbuj na chwilę zrobić coś innego. Następnie wróć do 🐪: albo wrócisz do lepszego świata, albo przyniesiesz ze sobą wiedzę o tym samym, abyśmy mogli wykorzystać twoją nową wiedzę, aby ulepszyć these w tych sprawach.


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


Oto co najmniej kilka rzeczy, które wydają się być wymagane, aby 🐪 „domyślnie włączał Unicode”, jak to ująłeś:

  1. Kod źródłowy 🐪 powinien być domyślnie w UTF-8. Możesz to uzyskać za pomocą use utf8lub export PERL5OPTS=-Mutf8.

  2. DATAUchwyt 🐪 powinien być UTF-8. Będziesz musiał to zrobić dla poszczególnych pakietów, jak w binmode(DATA, ":encoding(UTF-8)").

  3. Domyślnie argumenty programu do skryptów 🐪 powinny być rozumiane jako UTF-8. export PERL_UNICODE=Alub perl -CAlub export PERL5OPTS=-CA.

  4. Standardowe strumienie danych wejściowych, wyjściowych i błędów powinny być domyślnie ustawione na UTF-8. export PERL_UNICODE=Sdla wszystkich z nich, albo I, Oi / lub Edo tylko niektórych z nich. To jest jak perl -CS.

  5. Wszelkie inne uchwyty otwarte przez 🐪 powinny być traktowane jako UTF-8, chyba że podano inaczej; export PERL_UNICODE=Dlub z ii odla określonych z nich; export PERL5OPTS=-CDpracowałbym. To sprawia, że -CSADdla nich wszystkich.

  6. Pokryj obie bazy i wszystkie otwarte strumienie export PERL5OPTS=-Mopen=:utf8,:std. Zobacz unikat .

  7. Nie chcesz przegapić błędów kodowania UTF-8. Spróbować export PERL5OPTS=-Mwarnings=FATAL,utf8. I upewnij się, że twoje strumienie wejściowe są zawsze binmodedo :encoding(UTF-8), a nie tylko do :utf8.

  8. Punkty kodowe między 128–255 należy rozumieć przez 🐪 jako odpowiadające punkty kodowe Unicode, a nie tylko niepoprawne wartości binarne. use feature "unicode_strings"lub export PERL5OPTS=-Mfeature=unicode_strings. To sprawi, że uc("\xDF") eq "SS"i "\xE9" =~ /\w/. Prosty export PERL5OPTS=-Mv5.12lub lepszy również to dostanie.

  9. Nazwane znaki Unicode nie są domyślnie włączone, więc dodaj export PERL5OPTS=-Mcharnames=:full,:short,latin,greeklub niektóre z nich. Zobacz uninames i tcgrep .

  10. Prawie zawsze potrzebujesz dostępu do funkcji ze standardowego Unicode::Normalizemodułu różnego rodzaju rozkładów. export PERL5OPTS=-MUnicode::Normalize=NFD,NFKD,NFC,NFKD, a następnie zawsze uruchamiaj przychodzące rzeczy przez NFD i wychodzące rzeczy z NFC. Nie ma jeszcze dla nich żadnej warstwy I / O, ale zobacz nfc , nfd , nfkd i nfkc .

  11. Porównywanie łańcuchów w 🐪 użyciu eq, ne, lc, cmp, sort, & c & cc zawsze są błędne. Więc zamiast tego @a = sort @bpotrzebujesz @a = Unicode::Collate->new->sort(@b). Równie dobrze dodaj to do swojego export PERL5OPTS=-MUnicode::Collate. Możesz buforować klucz do porównań binarnych.

  12. 🐪 wbudowane lubią printfi writerobią coś złego z danymi Unicode. Trzeba korzystać z Unicode::GCStringmodułu dla tych pierwszych, i że zarówno a także moduł , jak również dla tych drugich. Zobacz uwc i unifmt .Unicode::LineBreak

  13. Jeśli chcesz, aby liczyły się jako liczby całkowite, będziesz musiał uruchomić \d+przechwytywanie przez Unicode::UCD::numfunkcję, ponieważ wbudowane atoi (3) 3 nie jest obecnie wystarczająco sprytne.

  14. Będziesz mieć problemy z systemem plików na 👽 systemach plików. Niektóre systemy plików po cichu wymuszają konwersję do NFC; inni po cichu wymuszają konwersję na NFD. A inni robią coś jeszcze. Niektórzy nawet całkowicie ignorują tę sprawę, co prowadzi do jeszcze większych problemów. Musisz więc zachować własną obsługę NFC / NFD, aby zachować rozsądek.

  15. Wszystkie Twoje 🐪 kod z udziałem a-zlub A-Zi takie muszą zostać zmienione , w tym m//, s///i tr///. Powinien się wyróżniać jako krzycząca czerwona flaga, że ​​Twój kod jest uszkodzony. Ale nie jest jasne, jak musi się to zmienić. Uzyskanie właściwych właściwości i zrozumienie ich folderów jest trudniejsze niż mogłoby się wydawać. Używam unichars i uniprops każdego dnia.

  16. Kod, który używa, \p{Lu}jest prawie tak samo zły, jak kod, który używa [A-Za-z]. Musisz użyć \p{Upper}zamiast tego i znać powód. Tak \p{Lowercase}i \p{Lower}różnią się od \p{Ll}i \p{Lowercase_Letter}.

  17. Kod, który używa, [a-zA-Z]jest jeszcze gorszy. I nie może użyć \pLlub \p{Letter}; musi użyć \p{Alphabetic}. Wiesz, nie wszystkie alfabetyty to litery.

  18. Jeśli szukasz 🐪 zmiennych /[\$\@\%]\w+/, masz problem. Musisz szukać /[\$\@\%]\p{IDS}\p{IDC}*/, a nawet to nie myśli o zmiennych interpunkcyjnych lub zmiennych pakietu.

  19. Jeśli sprawdzasz spacje, powinieneś wybrać pomiędzy \hi \v, w zależności od. I nigdy nie powinieneś używać \s, ponieważ NIE OZNACZA [\h\v] , wbrew powszechnemu przekonaniu.

  20. Jeśli używasz \ngranicy linii, a nawet \r\n, robisz to źle. Musisz użyć \R, co nie jest takie samo!

  21. Jeśli nie wiesz, kiedy i czy wywołać Unicode :: Stringprep , lepiej się naucz.

  22. Porównywania bez rozróżniania wielkości liter muszą sprawdzać, czy dwie rzeczy to te same litery, bez względu na ich znaki diakrytyczne i tym podobne. Najłatwiej to zrobić za pomocą standardowego modułu Unicode :: Collate . Unicode::Collate->new(level => 1)->cmp($a, $b). Istnieją również eqmetody i takie, i prawdopodobnie powinieneś również dowiedzieć się o metodach matchi substr. Są to wyraźne zalety w stosunku do wbudowanych 🐪.

  23. Czasami to wciąż za mało i zamiast tego potrzebujesz modułu Unicode :: Collate :: LocaleUnicode::Collate::Locale->new(locale => "de__phonebook", level => 1)->cmp($a, $b) . Uznaj Unicode::Collate::->new(level => 1)->eq("d", "ð")to za prawdę, ale za Unicode::Collate::Locale->new(locale=>"is",level => 1)->eq("d", " ð")fałsz. Podobnie „ae” i „æ” występują, eqjeśli nie używasz ustawień narodowych lub jeśli używasz języka angielskiego, ale różnią się one w islandzkich ustawieniach regionalnych. Co teraz? To trudne, mówię ci. Możesz grać z ucsort, aby przetestować niektóre z tych rzeczy.

  24. Zastanów się, jak dopasować wzór CVCV (konsonsant, samogłoska, spółgłoska, samogłoska) w ciągu „ niño ”. Jego forma NFD, którą lepiej zapamiętałeś, aby ją zapamiętać, staje się „nin \ x {303} o”. Co teraz zamierzasz zrobić? Nawet udając, że samogłoska jest [aeiou](co jest zresztą nie tak), nie będziesz w stanie zrobić czegoś takiego (?=[aeiou])\X), ponieważ nawet w NFD punkt kodowy taki jak „ø” nie ulega rozkładowi ! Jednak będzie to test równy „o” przy użyciu porównania UCA, które właśnie pokazałem. Nie możesz polegać na NFD, musisz polegać na UCA.


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


I to nie wszystko. Istnieje milion błędnych założeń, które ludzie robią na temat Unicode. Dopóki nie zrozumieją tych rzeczy, ich kod 🐪 zostanie złamany.

  1. Kod, który zakłada, że ​​może otwierać plik tekstowy bez określania kodowania, jest uszkodzony.

  2. Kod, który zakłada, że ​​domyślne kodowanie jest rodzimym kodowaniem platformy jest zepsuty.

  3. Kod, który zakłada, że ​​strony internetowe w języku japońskim lub chińskim zajmują mniej miejsca w UTF ‑ 16 niż w UTF ‑ 8, jest błędny.

  4. Kod, który zakłada, że ​​Perl wewnętrznie używa UTF ‑ 8, jest niepoprawny.

  5. Kod, który zakłada, że ​​błędy kodowania zawsze powodują wyjątek, jest niepoprawny.

  6. Kod, który zakłada, że ​​punkty kodu Perla są ograniczone do 0x10_FFFF, jest niepoprawny.

  7. Kod, który zakłada, że ​​możesz ustawić $/coś, co będzie działało z dowolnym poprawnym separatorem linii, jest niepoprawny.

  8. Kod, który zakłada równość w obie strony na foldery, podobnie jak lc(uc($s)) eq $slub uc(lc($s)) eq $s, jest całkowicie uszkodzony i niepoprawny. Weź pod uwagę, że oba są uc("σ")i uc("ς")oba "Σ", ale lc("Σ")prawdopodobnie nie mogą zwrócić obu z nich.

  9. Kod, który zakłada, że ​​każdy punkt kodu zapisany małymi literami ma wyraźny kod pisany wielkimi literami lub odwrotnie, jest uszkodzony. Na przykład "ª"jest małą literą bez wielkich liter; natomiast oba "ᵃ"i "ᴬ"są litery, ale nie są one małe litery; jednak oba są małymi punktami kodowymi bez odpowiednich wersji wielkich liter. Zrozumiałeś? Są nie \p{Lowercase_Letter} , mimo że zarówno \p{Letter}a \p{Lowercase}.

  10. Kod, który zakłada zmianę wielkości liter, nie zmienia długości łańcucha, jest uszkodzony.

  11. Kod, który zakłada, że ​​są tylko dwa przypadki, jest uszkodzony. Istnieje również titlecase.

  12. Kod, który zakłada, że ​​tylko litery mają wielkość liter, jest uszkodzony. Poza literami okazuje się, że cyfry, symbole, a nawet znaki mają duże litery. W rzeczywistości zmiana sprawy może nawet spowodować zmianę głównej kategorii ogólnej, na przykład \p{Mark}przekształcenie w \p{Letter}. Może także sprawić, że zmieni się z jednego skryptu na inny.

  13. Kod, który zakłada, że ​​wielkość liter nigdy nie zależy od ustawień regionalnych, jest uszkodzony.

  14. Kod, który zakłada, że ​​Unicode podaje informację o ustawieniach narodowych POSIX, jest uszkodzony.

  15. Kod, który zakłada, że ​​możesz usunąć znaki diakrytyczne, aby dostać się do podstawowych liter ASCII, jest zły, wciąż uszkodzony, uszkodzony, uszkodzony i usprawiedliwiony karą śmierci.

  16. Kod, który zakłada, że ​​znaki diakrytyczne \p{Diacritic}i znaki \p{Mark}są tym samym, jest łamany.

  17. Kod, który zakłada, że \p{GC=Dash_Punctuation}obejmuje tyle, ile \p{Dash}jest zepsuty.

  18. Kod, który zakłada myślnik, łączniki i minusy, są takie same, lub że jest tylko jeden, jest zepsuty i zły.

  19. Kod, który zakłada, że ​​każdy punkt kodu nie zajmuje więcej niż jednej kolumny wydruku, jest uszkodzony.

  20. Kod, który zakłada, że ​​wszystkie \p{Mark}znaki zajmują zero kolumn drukowania, jest uszkodzony.

  21. Kod, który zakłada, że ​​znaki podobne do siebie podobne, jest łamany.

  22. Kod, który zakłada, że ​​znaki, które nie wyglądają podobnie, nie są identyczne, jest łamany.

  23. Kod, który zakłada, że ​​istnieje ograniczenie liczby punktów kodu w rzędzie, które \Xmożna dopasować tylko jeden, jest nieprawidłowy.

  24. Kod, który zakłada, że \Xnigdy nie zaczyna się od \p{Mark}znaku, jest niepoprawny.

  25. Kod, który zakłada, że \Xnigdy nie może zawierać dwóch \p{Mark}znaków innych niż, jest niepoprawny.

  26. Kod, który zakłada, że ​​nie można go użyć, "\x{FFFF}"jest niepoprawny.

  27. Kod, który zakłada punkt kodowy inny niż BMP, który wymaga dwóch jednostek kodu UTF-16 (zastępczego), koduje dwa osobne znaki UTF-8, po jednym na jednostkę kodu, jest niepoprawny. Nie: koduje do pojedynczego punktu kodowego.

  28. Kod transkodujący z UTF ‐ 16 lub UTF ‐ 32 z wiodącymi BOM do UTF ‐ 8 jest uszkodzony, jeśli umieści BOM na początku wynikowego UTF-8. To takie głupie, że inżynier powinien mieć zdjęte powieki.

  29. Kod, który zakłada, że ​​CESU-8 jest prawidłowym kodowaniem UTF, jest niepoprawny. Podobnie kod, który myśli o kodowaniu U + 0000, podobnie jak "\xC0\x80"UTF-8, jest uszkodzony i niepoprawny. Ci faceci również zasługują na leczenie powiekami.

  30. Kod, który zakłada, że ​​znaki jak >zawsze wskazuje na prawo i <zawsze wskazuje na lewą stronę, są błędne - ponieważ w rzeczywistości tak nie jest.

  31. Kod, który zakłada, że ​​jeśli najpierw wypiszesz znak, Xa następnie znak Y, że będą one wyświetlane jako XYnieprawidłowe. Czasem nie.

  32. Kod, który zakłada, że ​​ASCII jest wystarczający do poprawnego pisania po angielsku, jest głupi, krótkowzroczny, niepiśmienny, łamany, zły i zły. Precz z głowami! Jeśli wydaje się to zbyt ekstremalne, możemy pójść na kompromis: odtąd mogą pisać tylko dużym palcem z jednej stopy. (Reszta zostanie nagrana taśmą klejącą.)

  33. Kod, który zakłada, że ​​wszystkie \p{Math}punkty kodu są widocznymi znakami, jest niepoprawny.

  34. Zakładany kod \wzawiera tylko litery, cyfry i podkreślenia jest niepoprawny.

  35. Kod, który zakłada, że ^i ~są znaki przestankowe jest źle.

  36. Kod, który zakłada, że üma umlaut, jest niepoprawny.

  37. Kod, który uważa, że ​​takie rzeczy zawierają jakiekolwiek litery, jest niepoprawny.

  38. Kod, który wierzy, \p{InLatin}jest taki sam, jak \p{Latin}potwornie złamany.

  39. Kod, który uważa, że \p{InLatin}jest prawie zawsze przydatny, prawie na pewno jest zły.

  40. Kod, który uważa, że ​​podany $FIRST_LETTERjako pierwsza litera w jakimś alfabecie i $LAST_LETTERjako ostatnia litera w tym samym alfabecie, który [${FIRST_LETTER}-${LAST_LETTER}]ma jakiekolwiek znaczenie, prawie zawsze jest całkowicie zepsuty, zły i bez znaczenia.

  41. Kod, który uważa, że ​​czyjeś imię może zawierać tylko niektóre znaki, jest głupi, obraźliwy i niewłaściwy.

  42. Kod, który próbuje zredukować Unicode do ASCII, nie jest po prostu zły, jego sprawca nigdy nie powinien mieć możliwości ponownego programowania. Kropka. Nie jestem nawet pewna, czy powinno się im znowu pozwolić zobaczyć, ponieważ jak dotąd nie przyniosło to im wiele dobrego.

  43. Kod, który uważa, że ​​istnieje jakiś sposób udawania, że ​​kodowanie plików tekstowych nie istnieje, jest uszkodzony i niebezpieczny. Równie dobrze może wystawić drugie oko.

  44. Kod, który zamienia nieznane znaki, ?jest zepsuty, głupi, braindead i działa wbrew standardowej rekomendacji, która mówi: NIE NALEŻY TO ROBIĆ!RTFM, dlaczego nie.

  45. Kod, który uważa, że ​​może niezawodnie odgadnąć kodowanie nieoznaczonego pliku tekstowego, jest winny fatalnej melanżu pychy i naiwności, którą naprawi tylko błyskawica Zeusa.

  46. Kod, który uważa, że ​​możesz użyć 🐪 printfszerokości do wypełniania i uzasadniania danych Unicode, jest uszkodzony i niepoprawny.

  47. Kod, który wierzy, że po pomyślnym utworzeniu pliku o danej nazwie, że po uruchomieniu lslub readdirw jego zamkniętym katalogu faktycznie znajdziesz ten plik pod nazwą, pod którą go utworzyłeś, jest wadliwy, uszkodzony i niewłaściwy. Przestań być tym zaskoczony!

  48. Kod, który uważa, że ​​UTF-16 jest kodowaniem o stałej szerokości, jest głupi, uszkodzony i niewłaściwy. Odwołaj ich licencję na programowanie.

  49. Kod, który traktuje punkty kodu z jednej płaszczyzny jeden odrobinę inaczej niż te z innej płaszczyzny, jest ipso facto uszkodzony i zły. Wracaj do szkoły.

  50. Kod, który uważa, że ​​takie rzeczy /s/imogą tylko pasować "S"lub "s"są zepsute i złe. Zdziwiłbyś się.

  51. Kod używany \PM\pM*do znajdowania klastrów grafemów zamiast używania \Xjest uszkodzony i niepoprawny.

  52. Ludzie, którzy chcą wrócić do świata ASCII, powinni być do tego szczerze zachęcani, a na ich chwalebne ulepszenie powinni otrzymać bezpłatnie elektryczną maszynę do pisania spełniającą wszystkie potrzeby w zakresie wprowadzania danych. Wiadomości wysyłane do nich powinny być wysyłane telegrafem w ilości 40 znaków na linię i dostarczane ręcznie przez kuriera. ZATRZYMAĆ.


😱 𝕾 𝖀 𝕸 𝕸 𝕬 𝕽 𝖄 😱


Nie wiem, o ile więcej „domyślnego Unicode w 🐪” można uzyskać, niż to, co napisałem. Cóż, tak, mam: powinieneś używać Unicode::CollateiUnicode::LineBreak . I prawdopodobnie więcej.

Jak widać, nie ma zbyt wiele rzeczy, Unicode, że naprawdę nie trzeba się martwić o tam na zawsze istnieje coś takiego jak „domyślnie do Unicode”.

Co odkryjesz, tak jak to zrobiliśmy w 🐪 5.8, że po prostu nie można narzucić tych wszystkich rzeczy na kod, który nie został zaprojektowany od samego początku, aby je uwzględnić. Wasze dobre intencje egoizm właśnie rozbił cały świat.

Nawet jeśli to zrobisz, nadal istnieją problemy krytyczne, które wymagają wiele przemyślenia, aby rozwiązać problem. Nie ma przełącznika, który można przerzucić. Wystarczy mózg, a mam na myśli prawdziwy mózg . Jest mnóstwo rzeczy, których musisz się nauczyć. Modulo wycofanie się do ręcznej maszyny do pisania, po prostu nie możesz mieć nadziei, że będziesz się wymykał w nieświadomości. Jest to 21ˢᵗ wiek i nie możesz życzyć Unicode umyślnej ignorancji.

Musisz się tego nauczyć. Kropka. To nigdy nie będzie tak łatwe, że „wszystko po prostu działa”, ponieważ gwarantuje to, że wiele rzeczy nie działa działało działa - co unieważnia założenie, że może istnieć sposób, aby „wszystko działało”.

Możesz uzyskać kilka rozsądnych ustawień domyślnych dla bardzo niewielu i bardzo ograniczonych operacji, ale nie bez myślenia o rzeczach o wiele bardziej niż myślę, że masz.

Jako jeden przykład, porządek kanoniczny spowoduje pewne bóle głowy. 😭 "\x{F5}" „õ” , "o\x{303}" „õ” , "o\x{303}\x{304}" „ȭ” i "o\x{304}\x{303}" „ō̃” powinny pasować do „õ” , ale jak, u licha , zamierzacie to zrobić? Jest to trudniejsze niż się wydaje, ale należy się z tym pogodzić. 💣

Jeśli jest coś, co wiem o Perlu, to to, co robią jego bity Unicode, a czego nie, i obiecuję ci: „̲ᴛ̲ʜ̲ᴇ̲ʀ̲ᴇ̲ ̲ɪ̲s̲ ̲ɴ̲ᴏ̲ ̲U̲ɴ̲ɪ̲ᴄ̲ᴏ̲ᴅ̲ᴇ̲ ̲ᴍ̲ᴀ̲ɢ̲ɪ̲ᴄ̲ ̲ʙ̲ᴜ̲ʟ̲ʟ̲ᴇ̲ᴛ̲ ̲” 😞

Nie możesz po prostu zmienić niektórych ustawień domyślnych i uzyskać płynnej żeglugi. To prawda, że ​​uruchamiam 🐪 z PERL_UNICODEustawionym na "SA", ale to wszystko, a nawet to dotyczy głównie wiersza poleceń. W prawdziwej pracy przechodzę przez wszystkie opisane powyżej kroki i robię to bardzo, ** bardzo ** ostrożnie.


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


56
Jak wskazał Sherm Pendley: „Wszyscy!”. Jeśli dziś napiszę coś nowego, UTF-8 powinien być najłatwiejszym sposobem na załatwienie sprawy. Nie jest. Twój bojler to potwierdza. Nie każdy ma taką wiedzę, aby obrócić tak wiele szklanek na właściwe pozycje. Przepraszam, miałem długi i ciężki dzień, więc jutro w komentarzu będę komentować więcej przykładów.
wk

17
Z powyższej listy powinien wynikać jeden wniosek: nie składaj wielkich liter. Po prostu nie. Zawsze. Kosztowne obliczeniowo i z semantyką, która zależy przede wszystkim od wszystkiego, co „locale” próbuje bezskutecznie zidentyfikować.
Tim Bray

72
Czy jestem jedynym, który uważa za ironię, że ten post autorstwa tchrista tak bardzo różni się na FF / Chrome / IE / Opera, aż do tego stopnia, że ​​jest nieczytelny?
damageboy

15
Chociaż ogólnie podoba mi się ten post i głosowałem, jedna rzecz mnie denerwuje. Istnieje wiele „kodów, które… są zepsute”. Chociaż nie kłócę się z tym stwierdzeniem, myślę, że dobrze byłoby pokazać złamanie. W ten sposób przejdzie (ta część odpowiedzi) od rantu do edukacji.

36
@xenoterracide Nie Nie użyłem celowo problematycznych punktów kodowych; jest to fabuła, w której musisz zainstalować niesamowitą czcionkę Symbola George'a Douros , która obejmuje Unicode 6.0. 😈 @depesz Nie ma tu miejsca na wyjaśnienie, dlaczego każde zepsute uderzenie jest złe. @leonbloy Wiele i wiele z tego dotyczy ogólnie Unicode, nie tylko Perla. Niektóre z tych materiałów mogą pojawić się w czwartym wydaniu 🐪 Programming Perl due, które ukaże się w październiku. 🎃 Został mi miesiąc do ✍ pracy nad tym, a Unicode jest ᴍᴇɢᴀ ; regexes też
tchrist

96

Istnieją dwa etapy przetwarzania tekstu Unicode. Pierwszym z nich jest „jak mogę go wprowadzić i wyprowadzić bez utraty informacji”. Drugi to „jak traktować tekst zgodnie z lokalnymi konwencjami językowymi”.

Post tchrista obejmuje oba te elementy, ale druga część to 99% tekstu jego postu. Większość programów nawet nie obsługuje poprawnie I / O, dlatego ważne jest, aby zrozumieć, że zanim zaczniesz martwić się o normalizację i zestawianie.

Ten post ma na celu rozwiązanie tego pierwszego problemu

Kiedy wczytujesz dane do Perla, nie ma znaczenia, jakie to kodowanie. Przydziela część pamięci i chowa tam bajty. Jeśli powieszprint $str , po prostu przenosi te bajty do twojego terminala, który prawdopodobnie jest ustawiony tak, aby zakładać, że wszystko, co jest w nim zapisane, to UTF-8, a twój tekst się pojawi.

Cudowny.

Tyle że nie. Jeśli spróbujesz traktować dane jako tekst, zobaczysz, że dzieje się coś złego. Nie musisz iść dalej niż lengthzobaczyć, co Perl myśli o twoim sznurku i co myślisz o sznurku się nie zgadza. Napisz jedno linijkę, taką jak: perl -E 'while(<>){ chomp; say length }'i wpisz, 文字化けa otrzymasz 12 ... nieprawidłowa odpowiedź, 4.

To dlatego, że Perl zakłada, że ​​twój ciąg nie jest tekstem. Musisz powiedzieć, że to tekst, zanim da ci właściwą odpowiedź.

To dość łatwe; moduł Encode ma do tego odpowiednie funkcje. Ogólny punkt wejścia to Encode::decode(lubuse Encode qw(decode) oczywiście). Ta funkcja pobiera ciąg znaków ze świata zewnętrznego (to, co nazwiemy „oktetami”, wymyślny sposób na powiedzenie „8-bitowych bajtów”), i zamienia go w tekst, który Perl zrozumie. Pierwszy argument to nazwa kodująca znak, na przykład „UTF-8” lub „ASCII” lub „EUC-JP”. Drugi argument to ciąg. Zwracana wartość to skalar Perl zawierający tekst.

(Jest też Encode::decode_utf8, który zakłada kodowanie UTF-8).

Jeśli przepiszemy jedną linijkę:

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

Wpisujemy 文字 化 け i otrzymujemy „4” jako wynik. Sukces.

To właśnie jest rozwiązanie 99% problemów z Unicode w Perlu.

Kluczem jest to, że za każdym razem, gdy jakiś tekst pojawia się w twoim programie, musisz go odkodować. Internet nie może przesyłać znaków. Pliki nie mogą przechowywać znaków. W bazie danych nie ma znaków. Są tylko oktety i nie można traktować oktetów jako znaków w Perlu. Musisz zdekodować zakodowane oktety na znaki Perla za pomocą modułu Encode.

Druga połowa problemu to pobieranie danych z programu. To łatwe; po prostu mówiszuse Encode qw(encode) , zdecyduj, w jakim kodowaniu będą twoje dane (UTF-8 do terminali, które rozumieją UTF-8, UTF-16 dla plików w systemie Windows itp.), a następnie wypisz wynik encode($encoding, $data)zamiast po prostu wypisywać $data.

Ta operacja przekształca znaki Perla, na których działa Twój program, w oktety, które mogą być używane przez świat zewnętrzny. Byłoby o wiele łatwiej, gdybyśmy mogli po prostu wysyłać znaki przez Internet lub do naszych terminali, ale nie możemy: tylko oktety. Musimy więc przekonwertować znaki na oktety, w przeciwnym razie wyniki nie zostaną zdefiniowane.

Podsumowując: zakoduj wszystkie wyjścia i odkoduj wszystkie wejścia.

Teraz porozmawiamy o trzech kwestiach, które sprawiają, że jest to trochę trudne. Pierwsza to biblioteki. Czy poprawnie obsługują tekst? Odpowiedź brzmi ... próbują. Jeśli pobierzesz stronę internetową, LWP zwróci ci wynik jako tekst. Jeśli wywołasz odpowiednią metodę w wyniku, to znaczy (i tak się składa decoded_content, że niecontent , to tylko strumień oktetów, który otrzymał z serwera). Sterowniki bazy danych mogą być niestabilne; jeśli użyjesz DBD :: SQLite tylko z Perlem, to zadziała, ale jeśli jakieś inne narzędzie umieściło w bazie danych tekst zapisany jako kodowanie inne niż UTF-8 ... cóż ... to nie będzie poprawnie obsługiwane dopóki nie napiszesz kodu, aby poprawnie go obsłużyć.

Wyprowadzanie danych jest zwykle łatwiejsze, ale jeśli widzisz „szeroki znak w druku”, to wiesz, że gdzieś psujesz kodowanie. To ostrzeżenie oznacza „hej, próbujesz wyciec postacie Perla do świata zewnętrznego i to nie ma żadnego sensu”. Twój program wydaje się działać (ponieważ drugi koniec zwykle poprawnie obsługuje nieprzetworzone znaki Perla), ale jest bardzo zepsuty i może przestać działać w dowolnym momencie. Napraw to wyraźnie Encode::encode!

Drugi problem to kod źródłowy zakodowany w UTF-8. O ile nie powiesz use utf8na górze każdego pliku, Perl nie przyjmie, że kod źródłowy to UTF-8. Oznacza to, że za każdym razem, gdy mówisz coś takiego my $var = 'ほげ', wstrzykujesz śmieci do swojego programu, który całkowicie psuje wszystko okropnie. Nie musisz „używać utf8”, ale jeśli nie, to należy nie używać żadnych znaków spoza ASCII w swoim programie.

Trzeci problem dotyczy tego, jak Perl radzi sobie z przeszłością. Dawno temu nie było czegoś takiego jak Unicode, a Perl założył, że wszystko jest tekstem Latin-1 lub binarnym. Więc kiedy dane przychodzą do twojego programu i zaczynasz traktować je jak tekst, Perl traktuje każdy oktet jako znak Latin-1. Właśnie dlatego, gdy poprosiliśmy o długość „文字 化 け”, otrzymaliśmy 12. Perl założył, że działamy na łańcuchu Latin-1 „æååã” (który ma 12 znaków, z których niektóre nie są drukowane).

Nazywa się to „niejawnym uaktualnieniem” i jest to całkowicie rozsądne, ale nie jest to pożądane, jeśli tekst nie jest w języku łacińskim-1. Dlatego tak ważne jest jawne odkodowanie danych wejściowych: jeśli tego nie zrobisz, Perl zrobi to i może zrobić to źle.

Ludzie wpadają w kłopoty, gdy połowa ich danych to ciąg znaków, a niektóre nadal są binarne. Perl zinterpretuje część, która wciąż jest binarna, tak jakby to był tekst Latin-1, a następnie połączy ją z poprawnymi danymi znakowymi. To sprawi, że będzie wyglądało na to, że prawidłowe zarządzanie postaciami zepsuło twój program, ale w rzeczywistości po prostu nie naprawiłeś go wystarczająco.

Oto przykład: masz program, który czyta plik tekstowy zakodowany w UTF-8, wstawiasz Unicode PILE OF POOdo każdej linii i drukujesz go. Piszecie tak:

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

Następnie uruchom niektóre dane zakodowane w UTF-8, takie jak:

perl poo.pl input-data.txt

Drukuje dane UTF-8 ze kupką na końcu każdej linii. Idealnie, mój program działa!

Ale nie, po prostu robisz binarną konkatenację. Czytasz oktety z pliku, usuwasz \nz chomp, a następnie dodajesz bajty w reprezentacji PILE OF POOznaku UTF-8 . Kiedy poprawisz swój program, aby zdekodować dane z pliku i zakodować dane wyjściowe, zauważysz, że zamiast śmieci kupujesz śmieci („ð ©”). Doprowadzi cię to do przekonania, że ​​dekodowanie pliku wejściowego jest niewłaściwe. To nie jest.

Problem polega na tym, że kupa jest domyślnie aktualizowana jako latin-1. Jeśli use utf8utworzysz dosłowny tekst zamiast binarny, to znowu zadziała!

(To jest problem numer jeden, który widzę, gdy pomagam ludziom z Unicode. Rozstali się dobrze i to zepsuło ich program. To jest smutne z powodu nieokreślonych wyników: możesz mieć działający program przez długi czas, ale kiedy zaczniesz go naprawiać, psuje się. Nie martw się; jeśli dodajesz do swojego programu instrukcje kodowania / dekodowania i psuje się, oznacza to, że masz więcej pracy do zrobienia. Następnym razem, kiedy projektujesz z myślą o Unicode od samego początku, będzie to dużo łatwiej!)

To naprawdę wszystko, co musisz wiedzieć o Perlu i Unicode. Jeśli powiesz Perlowi, jakie są twoje dane, ma najlepszą obsługę Unicode spośród wszystkich popularnych języków programowania. Jeśli zakładasz, że magicznie będzie wiedział, jaki rodzaj tekstu podajesz, to nieodwracalnie usuniesz swoje dane. To, że Twój program działa dzisiaj na terminalu UTF-8, nie oznacza, że ​​będzie działać jutro na pliku zakodowanym w UTF-16. Więc teraz to bezpieczne i oszczędzaj sobie kłopotów z usuwaniem danych użytkowników!

Łatwą częścią obsługi Unicode jest kodowanie danych wyjściowych i dekodowanie danych wejściowych. Trudność polega na znalezieniu wszystkich danych wejściowych i wyjściowych oraz ustaleniu, jakie to kodowanie. Ale dlatego dostajesz duże pieniądze :)


Zasada jest dobrze wyjaśniona, ale brakuje praktycznego podejścia do We / Wy. Jawne korzystanie z Encodemodułu jest żmudne i podatne na błędy, co sprawia, że ​​czytanie kodu dotyczącego operacji we / wy jest bardzo bolesne. Warstwy we / wy zapewniają rozwiązanie, ponieważ w razie potrzeby transparentnie kodują i dekodują. openi binmodepozwalają na ich specyfikację, a pragma openokreśla wartości domyślne, jak zalecił tchrist w swojej odpowiedzi.
Palec

48

Wszyscy zgadzamy się, że jest to trudny problem z wielu powodów, ale właśnie dlatego staramy się ułatwić wszystkim.

Istnieje najnowszy moduł CPAN, utf8 :: all , który próbuje „włączyć Unicode. Wszystko”.

Jak już wspomniano, nie można magicznie sprawić, aby cały system (programy zewnętrzne, zewnętrzne żądania sieciowe itp.) Również używał Unicode, ale możemy współpracować, aby tworzyć rozsądne narzędzia, które ułatwiają wykonywanie typowych problemów. Właśnie dlatego jesteśmy programistami.

Jeśli utf8 :: all nie robi czegoś, co według ciebie powinno, poprawmy to, aby było lepiej. Lub stwórzmy dodatkowe narzędzia, które razem mogą jak najlepiej odpowiadać na różne potrzeby ludzi.

`


5
Widzę wiele miejsca na ulepszenia w cytowanym utf8::allmodule. Został napisany przed unicode_stringsfunkcją, którą Fɪɴᴀʟʟʏ ᴀɴᴅ ᴀᴛ Lᴏɴɢ Lᴀsᴛ naprawia wyrażenia regularne, aby je mieć /u. Nie jestem przekonany, że rodzi to wyjątek dotyczący błędów kodowania i jest to coś, co naprawdę musisz mieć. Nie ładuje się w use charnames ":full"pragmie, która nie jest jeszcze automatycznie ładowana. Nie ostrzega o [a-z]takich printfszerokościach znaków, używając \nzamiast \Ri .zamiast \X, ale może to bardziej Perl::Critickwestia. Gdybym to był ja, dodałbym 𝐍𝐅𝐃 in and out.
tchrist

13
@tchrist Śledzenie problemów dla utf8 :: all jest tutaj. github.com/doherty/utf8-all/issues Bardzo chcieliby usłyszeć twoje sugestie.
Schwern

4
@ Schwern: ,s, ale nie krępuj się i oderwij od tego, co tu napisałem. Szczerze mówiąc, wciąż czuję / uczę się, co można zrobić, a co i gdzie. Oto dobry przykład przy rozładunku Sortowanie: unichars -gs '/(?=\P{Ll})\p{Lower}|(?=\P{Lu})\p{Upper}/x' | ucsort --upper | cat -n | less -r. Podobnie, małe kroki przygotowawcze, takie jak, ... | ucsort --upper --preprocess='s/(\d+)/sprintf "%#012d", $1/ge'mogą być naprawdę miłe i nie chciałbym podejmować za nich decyzji innych. Wciąż buduję zestaw narzędzi Unicode .
tchrist

35

Myślę, że źle rozumiesz Unicode i jego związek z Perlem. Bez względu na to, w jaki sposób przechowujesz dane, Unicode, ISO-8859-1 lub wiele innych rzeczy, twój program musi wiedzieć, jak interpretować bajty, które otrzymuje jako dane wejściowe (dekodowanie) i jak reprezentować informacje, które chce wyprowadzić (kodowanie) ). Błędnie zinterpretuj tę interpretację, a będziesz marnować dane. W twoim programie nie ma żadnej magicznej domyślnej konfiguracji, która powiedziałaby osobom spoza programu, jak się zachować.

Myślisz, że to trudne, najprawdopodobniej, ponieważ jesteś przyzwyczajony do wszystkiego, co ASCII. Wszystko, o czym powinieneś pomyśleć, zostało po prostu zignorowane przez język programowania i wszystkie rzeczy, z którymi musiał wchodzić w interakcje. Gdyby wszystko wykorzystywało tylko UTF-8 i nie miałeś wyboru, to UTF-8 byłoby równie łatwe. Ale nie wszystko korzysta z UTF-8. Na przykład, nie chcesz, aby Twój uchwyt wejściowy myślał, że pobiera oktety UTF-8, chyba że tak naprawdę jest, i nie chcesz, aby twoje uchwyty wyjściowe były UTF-8, jeśli odczyt z nich może obsłużyć UTF-8 . Perl nie ma sposobu, aby poznać te rzeczy. Dlatego jesteś programistą.

Nie sądzę, aby Unicode w Perlu 5 był zbyt skomplikowany. Myślę, że to przerażające i ludzie tego unikają. Jest różnica. W tym celu umieściłem Unicode w Learning Perl, 6. edycja , i jest wiele rzeczy w Unicode w Effective Perl Programming . Musisz poświęcić czas na naukę i zrozumienie Unicode oraz jego działania. W przeciwnym razie nie będziesz w stanie efektywnie z niego korzystać.


3
Myślę, że masz rację: to jest przerażające. Tak być powinno? Dla mnie jest to błogosławieństwo Unicode, nie jest ono używane w Perl5 (nie zakładam, że ASCII, mój język ojczysty wymaga co najmniej iso8859-4). Zainstalowałem Rakudo i wszystko, czego próbowałem z UTF-8 (w tym ograniczonym piaskownicy) działało od razu. Przegapiłem coś? Podkreślam to jeszcze raz: dobrze jest mieć dopracowaną obsługę Unicode, ale w większości przypadków nie jest to potrzebne. Aby oderwać się od tematu, jednym ze sposobów jest to, że wszyscy dużo czytają, aby zrozumieć elementy wewnętrzne. Inne: mamy szczególną pragmę, dlatego use utf8_everywhereludzie są szczęśliwi. Dlaczego nie ostatni?
wk

3
Nadal uważam, że nie rozumiesz. Co zadziałało Nie musisz rozumieć wewnętrznych elementów. Musisz zrozumieć elementy zewnętrzne i sposób obsługi ciągów, które mają różne kodowania i różne reprezentacje tych samych znaków. Przeczytaj ponownie radę Toma. Większość tego, co mówi, założę się, że przekonasz się, że Rakudo ci nie odpowiada.
brian d foy

1
@ wk: Przeczytaj ponownie odpowiedź Randy'ego. Już ci powiedział, jakie są ograniczenia.
brian d foy

2
@brian d foy: Myślę, że te ograniczenia są w porządku, jak mówi tchrist, nie ma magicznej kuli dla każdego aspektu (przyznaję: nie widziałem większości z nich przed zadaniem tego pytania tutaj). Tak więc, kiedy omawiamy wiele podstawowych rzeczy za pomocą czegoś takiego jak utf8 :: all, nie ma potrzeby, aby każdy budował swój własny wielki kocioł, tylko po to, aby uzyskać podstawy obsługi utf8 do pracy. Mam na myśli „w ogóle się nie boję”: każdy może rozpocząć swój projekt, wiedząc, że są w nim podstawy. Tak, masz rację, wciąż jest wiele problemów. Ale kiedy rozpoczęcie jest łatwiejsze, będziemy mieć więcej osób zaangażowanych w ich rozwiązywanie. IMHO
wk

1
@wk - jedyny „zły” z „utf8: all” lub „uni :: perl jest tylko jeden - nie ma go w rdzeniu - więc każdy musi go zainstalować z CPAN. A jeśli uważasz, że to nie jest duży umowa - przemyśl proszę - tak, łatwiej jest używać utf8 z modułem pomocniczym. Bez tego perl CORE nadal ma obsługę Unicode - ale o wiele bardziej skomplikowany. I to jest złe.
jm666

28

Czytając ten wątek, często mam wrażenie, że ludzie używają „ UTF-8 ” jako synonimu „ Unicode ”. Dokonaj rozróżnienia między „punktami kodowymi” Unicode, które są powiększonymi krewnymi kodu ASCII, a różnymi „kodowaniami” Unicode. Jest ich kilka, w tym UTF-8, UTF-16 i UTF-32 , a kilka innych jest przestarzałych.

Proszę, UTF-8 (jak również wszystkie inne kodowania ) istnieje i ma znaczenie tylko na wejściu lub wyjściu. Wewnętrznie od wersji 5.8.1 wszystkie ciągi znaków są przechowywane jako „punkty kodowe” w standardzie Unicode. To prawda, że ​​musisz włączyć niektóre funkcje, które wcześniej były podziwiane.


19
Zgadzam się, że ludzie zbyt często mylą Uɴɪᴄᴏᴅᴇ z UTF-8⧸16⧸32, ale zasadniczo i krytycznie nie jest prawdą, że Uɴɪᴄᴏᴅᴇ jest tylko rozszerzonym zestawem znaków w stosunku do ᴀsᴄɪɪ. Co najwyżej to nic więcej niż zwykłe „106” . Uɴɪᴄᴏᴅᴇ obejmuje znacznie więcej : zasady zestawiania, składania liter, formularzy normalizacyjnych, klastrów grafemów, dzielenia wyrazów i wierszy, skrypty, równania liczbowe, szerokości, dwukierunkowość, warianty glifów, zachowanie kontekstowe, lokalizacje, wyrażenia regularne, łączenie klas, setki właściwości, i znacznie więcej‼
tchrist

15
@tchrist: pierwszym krokiem jest przeniesienie danych do twojego programu i wyjście na zewnątrz bez niszczenia go. wtedy możesz się martwić o sortowanie, składanie skrzynek, warianty glifów itp. kroki dziecka.
jrockway

7
Zgadzam się, aby Perl nie wyrzucał do kosza danych wejściowych ani wyjściowych, musi być priorytetem. Chciałbym mieć moduł lub pragmę, która mogłaby zawierać w sobie następującą fikcyjną rozmowę: „- Drogi Perlu. Dla tego programu wszystkie dane wejściowe i wyjściowe będą dotyczyły wyłącznie UTF-8. Czy mógłbyś nie wyrzucać moich danych? - Więc mówisz tylko o UFT-8. Jesteś pewien? - Tak - Naprawdę, naprawdę pewny? - Oczywiście. - I akceptujesz, że mógłbym się dziwnie zachowywać, jeśli dostanę dane inne niż UTF-8? - Tak, w porządku. - Ok, więc. ”
hlovdal

10

Na wolności jest naprawdę przerażająca ilość starożytnego kodu, w dużej mierze w postaci wspólnych modułów CPAN. Odkryłem, że muszę dość ostrożnie włączać Unicode, jeśli korzystam z zewnętrznych modułów, na które może mieć wpływ, i nadal próbuję zidentyfikować i naprawić niektóre błędy związane z Unicode w kilku skryptach Perla, których regularnie używam (w szczególności iTiVo nie działa źle na wszystkim, co nie jest 7-bitowym ASCII z powodu problemów z transkodowaniem).


Miałem na myśli skorzystanie z -Copcji, aby upewnić się, że Perl jest na tej samej stronie, co ja, jeśli chodzi o Unicode, ponieważ wciąż decyduję się na użycie ISO 8859/1 zamiast Unicode, mimo że jawnie ustawiam $LANGi $LC_ALLpoprawnie. (Może to faktycznie odzwierciedlać błędy w bibliotekach regionalnych platformy.) Cokolwiek to jest, bardzo denerwujące jest to, że nie mogę używać iTivo w programach z akcentami, ponieważ skrypty Perla, które wykonują pracę, przewracają się z błędami konwersji.
geekozaur

3
Samotny -Cbez opcji jest podatny na błędy i błędy . Rozbijasz świat. Ustaw PERL5OPTzmienną na, -Ca zobaczysz, co mam na myśli. Próbowaliśmy tego w wersji v8.8 i była to katastrofa. Po prostu nie możesz i nie wolno informować programów, które się tego nie spodziewają, że teraz mają do czynienia z Unicode, czy im się to podoba, czy nie. Istnieją również problemy z bezpieczeństwem. Przynajmniej wszystko, co print while <>się zepsuje, jeśli zostaną przekazane dane binarne. Podobnie będzie z całym kodem bazy danych. To okropny pomysł.
tchrist

1
Mówiłem ogólnie, właściwie nie specjalnie -Cbez opcji. Konkretne wywołanie, z którym pracowałem, to -CSDA. To powiedziawszy, utknąłem z 5.8.x przez długi czas (cześć MacPorts ...), więc może to było częścią tego.
geekozaur

1
Pracuję z PERL_UNICODE ustawionym na SA. Ty NIE MOŻE ustawić go do D.
tchrist

@tchrist: Niektóre wersje Perla publikują kod pokazujący użycie -CSDA i PERL_UNICODE = użycie SDA . Proszę użyć swojego wpływu w społeczności. Musi zostać zatrzymany!
Ashley

1

Powinieneś włączyć funkcję ciągów znaków Unicode, a jest to ustawienie domyślne, jeśli używasz v5.14;

Naprawdę nie powinieneś używać identyfikatorów Unicode esp. dla obcego kodu za pośrednictwem utf8, ponieważ nie są one bezpieczne w perl5, tylko cperl miał to poprawnie. Zobacz np. Http://perl11.org/blog/unicode-identifiers.html

Odnośnie utf8 dla twoich uchwytów / strumieni plików: Musisz sam zdecydować o kodowaniu swoich danych zewnętrznych. Biblioteka nie może tego wiedzieć, a ponieważ nawet libc nie obsługuje utf8, prawidłowe dane utf8 są rzadkie. Wokół jest więcej wtf8, aberracja systemu Windows w utf8.

BTW: Łoś nie jest tak naprawdę „Modern Perl”, po prostu porwał nazwę. Łoś jest idealny postmodernistyczny perl w stylu Larry'ego Walla i wszystko w stylu Bjarne Stroustrup, z eklektyczną aberracją właściwej składni perl6, np. Używając ciągów znaków dla zmiennych nazw, składni strasznych pól i bardzo niedojrzałej naiwnej implementacji, która jest 10 razy wolniejsza niż prawidłowe wdrożenie. cperl i perl6 są prawdziwymi nowoczesnymi perlami, w których forma podąża za funkcją, a implementacja jest ograniczona i zoptymalizowana.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.