Чому сучасний Perl за замовчуванням уникає UTF-8?


557

Цікаво, чому більшість сучасних рішень, побудованих за допомогою Perl, не включають UTF-8 за замовчуванням.

Я розумію, що для основних сценаріїв Perl існує багато проблем, де це може порушити справи. Але, з моєї точки зору, в 21 - м столітті, великі нові проекти (або проекти з великою перспективою) повинні зробити їх програмне забезпечення UTF-8 доказ з нуля. Але я не бачу цього. Наприклад, Moose включає суворі та попередження, але не Unicode . Сучасний :: Perl також зменшує котельну плиту, але ніякої обробки UTF-8.

Чому? Чи є причини, щоб у 2011 році уникати UTF-8 у сучасних проектах Perl?


Коментувати @tchrist було занадто довго, тому я додаю його тут.

Здається, я не дав зрозуміти. Дозвольте спробувати додати деякі речі.

tchrist, і я бачу ситуацію приблизно аналогічно, але наші висновки повністю у протилежних цілях. Я погоджуюся, ситуація з Unicode є складною, але саме тому нам (користувачам Perl та кодерам) потрібен певний шар (або прагма), що робить обробку UTF-8 настільки простою, як це має бути в наш час.

tchrist вказав на багато аспектів, які слід висвітлити, я буду читати і думати про них днями чи навіть тижнями. Все-таки це не моя суть. tchrist намагається довести, що не існує одного єдиного способу "включити UTF-8". Я не так багато знань, щоб посперечатися з цим. Отже, я дотримуюся живих прикладів.

Я грав з Ракудо, і UTF-8 був просто там, як мені потрібно . У мене не було жодних проблем, це просто спрацювало. Можливо, є якесь обмеження десь глибше, але на початку все тестуване працювало так, як я очікував.

Це не повинно бути ціллю і в сучасному Perl 5? Я наголошую на цьому більше: я не пропоную UTF-8 в якості набору символів за замовчуванням для основного Perl, пропоную можливість запустити його з оснащенням для тих, хто розробляє нові проекти.

Ще один приклад, але з більш негативним тоном. Рамки повинні полегшити розвиток. Деякі роки тому я спробував веб-фреймворки, але просто викинув їх, бо "включення UTF-8" було таким незрозумілим. Я не знайшов, як і де підключити підтримку Unicode. Це було настільки трудомістким, що мені стало легше йти старим шляхом. Тепер я побачив, що тут було щедро вирішити цю проблему з Мейсоном 2: Як зробити Mason2 UTF-8 чистим? . Отже, це доволі нова рамка, але для використання її з UTF-8 потрібні глибокі знання про її внутрішнє середовище. Це як великий червоний знак: СТОПУЙ, не використовуй мене!

Мені дуже подобається Perl. Але мати справу з Unicode - болісно. Я все ще опиняюся на стінах. Якимось чином тріст є правильним і відповідає на мої запитання: нові проекти не приваблюють UTF-8, оскільки це дуже складно в Perl 5.


15
Вибачте, але я згоден з @tchrist - UTF-8 надзвичайно важкий. Немає рамки чи інструменту, який би просто "перемикав перемикач" і потім правильно поводився з ним. Це те, про що ви повинні безпосередньо задуматися, розробляючи свою програму, - не те, з чим можуть працювати будь-які рамки чи мови. Якщо ракудо просто трапилось на вас, ви не були достатньо захоплені своїми тестовими кейсами - оскільки це займе кілька прикладів у відповіді та м'яснику @ tchrist.
Біллі ONeal

12
Що саме ви сподіваєтеся, що зробить Moose або Modern :: Perl? Заново магічно перетворити випадкові кодовані символьні дані у файли та бази даних у дійсні дані?
jrockway

13
Що це означає? Лось не має нічого спільного з текстовими маніпуляціями. Чому слід знати про кодування символів, а тим більше вибирати стандартне для вас? (У будь-якому випадку, причина списку прагм не торкається кодування полягає в тому, що умова передбачає, що прагми Perl впливають на лексичну поведінку. Якщо припустити, що весь світ, включаючи інші модулі, є UTF-8, це просто неправильна річ. . Тут це не PHP чи Ruby.)
jrockway

8
(Також ... "найсучасніші додатки Perl" ламаються на UTF-8? Я, звичайно, ніколи не писав заявки, Perl чи іншим чином, це не Unicode-чисто.)
jrockway

11
Nb. tchrist (Том Крістіансен) опублікував свої [ training.perl.com/OSCON2011/index.html Матеріали Тома Крістіанасена для OSCON 2011] про Unicode. Той, що має назву "Перестрілка Unicode підтримки: хороший, поганий та (здебільшого) некрасивий", говорить про підтримку Unicode на різних мовах програмування. Тільки Google Go і Perl5 підтримують повний Unicode, лише Google Go вбудований (не згадуючи про Perl6).
Якуб Нарбський

Відповіді:


1146

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

  1. Встановіть свою PERL_UNICODEперевагу AS. Завдяки цьому всі сценарії Perl декодуються @ARGVяк рядки UTF-8, а кодування всіх трьох stdin, stdout та stderr встановлюється в UTF-8. І те, і інше - це глобальні наслідки, а не лексичні.

  2. У верхній частині вихідного файлу (програма, модуль, бібліотека, doперехід) чітко запевняйте, що ви запускаєте версію perl версії 5.12 або вище за допомогою:

    use v5.12;  # minimal for unicode string feature
    use v5.14;  # optimal for unicode string feature
  3. Увімкніть попередження, оскільки попередня декларація передбачає лише суворі функції та функції, а не попередження. Я також пропоную просувати попередження Unicode у винятки, тому використовуйте обидва ці рядки, а не лише один із них. Однак зверніть увагу , що при v5.14, то utf8клас попередження включає в себе три інших subwarnings , які все можуть бути окремо включені: nonchar, surrogate, і non_unicode. Ці, можливо, ви хочете посилити контроль над ними.

    use warnings;
    use warnings qw( FATAL utf8 );
  4. Заявіть, що цей вихідний блок кодується як UTF-8. Хоча колись ця прагма робила інші речі, вона тепер служить цій єдиній цілі самостійно і нічим іншим:

    use utf8;
  5. Зазначте, що все, що відкриває файл файлів у межах цього лексичного простору, але не в іншому місці, - припустити, що цей потік закодований у UTF-8, якщо ви не скажете це інше. Таким чином ви не вплинете на код іншого модуля чи іншої програми.

    use open qw( :encoding(UTF-8) :std );
  6. Увімкнути названі символи через \N{CHARNAME}.

    use charnames qw( :full :short );
  7. Якщо у вас є DATAручка, ви повинні чітко встановити її кодування. Якщо ви хочете, щоб це було UTF-8, тоді скажіть:

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

Звичайно, не існує кінця з іншими питаннями, з якими ви, зрештою, можете виявити себе стурбованими, але їх буде достатньо, щоб наблизити державну мету до того, щоб "все просто працювало з UTF-8", хоча і дещо ослаблений сенс цих термінів.

Ще одна прагма, хоча вона не пов'язана з Unicode, це:

      use autodie;

Настійно рекомендується.

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


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


Моя власна котельня сьогодні має такий вигляд:

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__

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


Кажучи, що «Перл повинен [ якось! ] включити Unicode за замовчуванням »навіть не починає думати про те, щоб обійтись, щоб сказати достатньо, щоб бути навіть незначно корисним у якомусь рідкісному та ізольованому випадку. Unicode - це набагато більше, ніж просто більший репертуар персонажів; це також, як ці персонажі взаємодіють у багатьох, багатьох способах.

Навіть простодушні мінімальні заходи, які (деякі) люди, здається, вважають, що хочуть, гарантовано зламують мільйони рядків коду, коду, який не має шансів «модернізуватися» до вашої шикарної нової відважної сучасності Нового Світу .

Це спосіб шляху складніший, ніж прикидаються люди. Я думав про це величезну, цілу багато за останні кілька років. Я хотів би, щоб мені показали, що я помиляюся. Але я не думаю, що я є. Unicode принципово складніший, ніж модель, яку ви хотіли б нав'язати йому, і тут є складність, яку ви ніколи не зможете підмітати під килим. Якщо ви спробуєте, ви зламаєте або власний код, або чужий код. У якийсь момент ви просто повинні зламатись і дізнатися, що таке Unicode. Ви не можете робити вигляд, що це щось не так.

🐪 виходить із шляху, щоб зробити Unicode легким, набагато більше, ніж усе, що я коли-небудь використовував. Якщо ви вважаєте, що це погано, спробуйте щось на деякий час. Тоді поверніться до 🐪: або ви повернетесь у кращий світ, або ж принесете знання про те саме, щоб ми могли використати ваші нові знання, щоб зробити 🐪 кращими в цих речах.


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


Як мінімум, ось деякі речі, які, здається, потрібні для 🐪, щоб "включити Unicode за замовчуванням", як ви сказали:

  1. Весь 🐪 вихідний код повинен бути за замовчуванням у UTF-8. Ви можете отримати це за допомогою use utf8або export PERL5OPTS=-Mutf8.

  2. DATAРучка 🐪 повинна бути UTF-8. Вам доведеться робити це за кожну упаковку, як в binmode(DATA, ":encoding(UTF-8)").

  3. Аргументи програми для 🐪 скриптів слід розуміти як стандартні UTF-8. export PERL_UNICODE=A, або perl -CA, або export PERL5OPTS=-CA.

  4. Стандартні потоки вводу, виводу та помилок мають бути типовими для UTF-8. export PERL_UNICODE=Sдля всіх, або I, Oта / або Eлише для деяких з них. Це як perl -CS.

  5. Будь-які інші ручки, відкриті 🐪, слід вважати UTF-8, якщо не заявлено інше; export PERL_UNICODE=Dабо iі oдля конкретних з них з них; export PERL5OPTS=-CDпрацювали б. Це робить -CSADдля всіх них.

  6. Накрийте обидві бази плюс усі потоки, якими ви відкриваєтесь export PERL5OPTS=-Mopen=:utf8,:std. Дивіться однозначне .

  7. Ви не хочете пропускати помилки кодування UTF-8. Спробуйте export PERL5OPTS=-Mwarnings=FATAL,utf8. І переконайтеся, що ваші потоки вводу завжди binmodeвідзначаються :encoding(UTF-8), а не тільки :utf8.

  8. Точки коду між 128–255 слід розуміти 🐪 як відповідні кодові точки Unicode, а не просто невлаштовані бінарні значення. use feature "unicode_strings"або export PERL5OPTS=-Mfeature=unicode_strings. Це зробить uc("\xDF") eq "SS"і "\xE9" =~ /\w/. Простий export PERL5OPTS=-Mv5.12чи кращий також отримає це.

  9. Іменовані символи Unicode за замовчуванням не включені, тому додайте export PERL5OPTS=-Mcharnames=:full,:short,latin,greekабо кілька таких. Див. Імена та tcgrep .

  10. Ви майже завжди потребуєте доступу до функцій зі стандартного Unicode::Normalizeмодуля різних типів декомпозицій. export PERL5OPTS=-MUnicode::Normalize=NFD,NFKD,NFC,NFKD, а потім завжди запускайте вхідні матеріали через NFD та вихідні матеріали з NFC. Для них ще немає шару вводу / виводу, про який я знаю, але дивіться nfc , nfd , nfkd і nfkc .

  11. Порівняння рядків в 🐪 використовуючи eq, ne, lc, cmp, sort, і з & куб.см завжди неправі. Тож замість цього @a = sort @bвам потрібно @a = Unicode::Collate->new->sort(@b). Можна також додати це до свого export PERL5OPTS=-MUnicode::Collate. Ви можете кешувати ключ для бінарних порівнянь.

  12. Вбудовані дані як printfі writeроблять неправильно з даними Unicode. Ви повинні використовувати в Unicode::GCStringмодуль для першого, і як то, що і також модуль , а для останнього. Дивіться uwc та unifmt .Unicode::LineBreak

  13. Якщо ви хочете, щоб порахувати як цілі числа, то ви будете мати , щоб запустити свої \d+знімки з допомогою в Unicode::UCD::numфункції , тому що 🐪 побудований в atoi (3) в даний час недостатньо розумний.

  14. У вас виникнуть проблеми з файловою системою у 👽 файлових системах. Деякі файлові системи мовчки здійснюють перетворення на NFC; інші мовчки здійснюють перехід на NFD. А інші ще щось роблять. Деякі навіть ігнорують справу взагалі, що призводить до ще більших проблем. Таким чином, вам потрібно зробити власну обробку NFC / NFD, щоб залишатися здоровими.

  15. Всі ваші 🐪 код з участю a-zабо A-Zй такі повинні бути змінені , в тому числі m//, s///і tr///. Це повинно виділятися кричущим червоним прапором, що ваш код порушений. Але не ясно, як це має змінитися. Отримати правильні властивості та зрозуміти їх складність складніше, ніж ви могли подумати. Я використовую одноразові та uniprops щодня.

  16. Код, який використовується \p{Lu}, майже так само неправильно, як і код, який використовується [A-Za-z]. Вам потрібно використовувати \p{Upper}замість цього і знати причину. Так, \p{Lowercase}і \p{Lower}відрізняються від \p{Ll}і \p{Lowercase_Letter}.

  17. Код, який використовує [a-zA-Z], ще гірше. І він не може використовувати \pLабо \p{Letter}; це потрібно використовувати \p{Alphabetic}. Не всі букви - це букви, знаєте!

  18. Якщо ви шукаєте 🐪 змінних з /[\$\@\%]\w+/, тоді у вас є проблема. Вам потрібно шукати /[\$\@\%]\p{IDS}\p{IDC}*/, і навіть це не замислюється про розділові знаки або змінні пакету.

  19. Якщо ви перевіряєте пробіл, слід вибирати між \hта \vзалежно від цього. І ніколи не слід користуватися \s, оскільки це НЕ ЗНАЄ [\h\v] , всупереч поширеній думці.

  20. Якщо ви використовуєте \nдля межі лінії чи навіть \r\n, ви робите це неправильно. Ви повинні користуватися \R, що не те саме!

  21. Якщо ви не знаєте, коли і чи потрібно викликати Unicode :: Stringprep , тоді вам краще навчитися.

  22. Незалежно від регістру порівняння потрібно перевірити, чи є дві речі однаковими літерами незалежно від їх діакритичності та подібних. Найпростіший спосіб зробити це зі стандартним модулем Unicode :: Collate . Unicode::Collate->new(level => 1)->cmp($a, $b). Існують eqі такі методи, і ви, напевно, також повинні дізнатися про методи matchта substrметоди. Вони мають чіткі переваги перед 🐪 вбудованими.

  23. Іноді цього все ще недостатньо, і вам потрібен модуль Unicode :: Collate :: Locale , як Unicode::Collate::Locale->new(locale => "de__phonebook", level => 1)->cmp($a, $b)замість цього. Вважайте, що Unicode::Collate::->new(level => 1)->eq("d", "ð")це правда, але Unicode::Collate::Locale->new(locale=>"is",level => 1)->eq("d", " ð")неправда. Аналогічно, "ae" і "æ" - це eqякщо ви не використовуєте локалі, або якщо ви використовуєте англійський, але вони відрізняються в ісландській мові. А тепер що? Я важко кажу вам. Ви можете пограти з ucsort, щоб перевірити деякі з цих речей.

  24. Розглянемо, як узгодити шаблон CVCV (приголосний, голосний, приголосний, голосний) у рядку “ niño ”. Його форма NFD - яку ви добре відмітили, пам'ятаєте, що це було зроблено - стає "nin \ x {303} o". Тепер що ти будеш робити? Навіть роблячи вигляд, що голосна є [aeiou](що, до речі, неправильно), ви не зможете зробити щось подібне (?=[aeiou])\X), тому що навіть у NFD кодова точка на зразок 'ø' не розкладається ! Однак це буде тест рівним 'o', використовуючи порівняння UCA, яке я вам щойно показав. Ви не можете покластися на NFD, ви повинні розраховувати на UCA.


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


І це ще не все. Є мільйон порушених припущень, які люди роблять щодо Unicode. Поки вони не зрозуміють ці речі, їх 🐪 код буде порушений.

  1. Код, який передбачає, що він може відкрити текстовий файл, не вказуючи, що кодування порушено.

  2. Код, який передбачає кодування за замовчуванням, - це якесь кодування рідної платформи.

  3. Код, який передбачає, що веб-сторінки японською або китайською мовами займають менше місця в UTF-16, ніж в UTF-8, є неправильним.

  4. Код, який передбачає, що Perl використовує UTF-8 внутрішньо, неправильний.

  5. Код, який передбачає, що помилки кодування завжди спричиняють виняток, є неправильним.

  6. Код, який передбачає, що кодові точки Perl обмежені 0x10_FFFF, неправильний.

  7. Код, який передбачає, що ви можете встановити $/щось, що буде працювати з будь-яким дійсним роздільником рядків, неправильно.

  8. Код, який передбачає рівність прямого звороту на випадок, як-от lc(uc($s)) eq $sабо uc(lc($s)) eq $s, повністю порушений і неправильний. Вважайте, що uc("σ")і те, і те uc("ς") й інше "Σ", але lc("Σ")неможливо повернути обоє.

  9. Код, який передбачає, що в кожній малій кодовій точці є чітка велика, або навпаки, порушений. Наприклад, "ª"це малі літери без великих літер; оскільки обидва "ᵃ"і "ᴬ"букви, але вони не є малими літерами; однак вони є обома малими кодовими точками без відповідних великих версій. Зрозумів? Вони не є \p{Lowercase_Letter}, незважаючи на те, що вони є \p{Letter}і \p{Lowercase}.

  10. Код, який передбачає зміну регістру, не змінює довжину рядка.

  11. Код, який передбачає, що є лише два випадки, порушений. Також є заголовок.

  12. Код, який передбачає, що лише літери мають регістр, порушений. Окрім букв, виявляється, що цифри, символи та навіть знаки мають місце. Насправді, зміна справи може навіть змусити щось змінити її основну загальну категорію, як \p{Mark}перетворення на а \p{Letter}. Це також може змусити його переходити від одного сценарію до іншого.

  13. Код, який передбачає, що випадок ніколи не залежить від локалі, порушується.

  14. Код, який передбачає, що Unicode дає фігу про локалі POSIX, порушено.

  15. Код, який передбачає, що ви можете зняти діакритику, щоб отримати в базі ASCII літери - це зло, нерухоме, зламане, пошкоджене мозку, неправильне та виправдання для смертної кари.

  16. Код, який передбачає, що діакритика \p{Diacritic}та позначення \p{Mark}- це одне і те ж, порушено.

  17. Код, який передбачає \p{GC=Dash_Punctuation}обкладинку стільки, скільки \p{Dash}порушено.

  18. Код, який передбачає тире, дефіси та мінуси - це те саме, що один у одного, або що у кожного є лише один, порушений і неправильний.

  19. Код, який передбачає, що кожна точка коду займає не більше одного стовпчика друку, порушено.

  20. Код, який передбачає, що всі \p{Mark}символи займають нульові стовпці друку, порушено.

  21. Код, який передбачає, що символи, схожі на них , порушені.

  22. Код, який передбачає, що символи, які не схожі на себе, не однакові, порушені.

  23. Код, який передбачає, що існує обмеження на кількість точок коду у рядку, з яким \Xможе відповідати лише одна, - це неправильно.

  24. Код, який передбачає, що \Xніколи не може починатися з \p{Mark}символу, є неправильним.

  25. Код, який передбачає, що \Xніколи не може містити двох не \p{Mark}символів, є неправильним.

  26. Код, який передбачає, що він не може використовуватись "\x{FFFF}", неправильний.

  27. Код, який передбачає кодову точку, що не належить до BMP, що вимагає двох кодів UTF-16 (сурогатних), буде кодувати до двох окремих символів UTF-8, по одному на кодову одиницю, неправильно. Це не так: він кодує одну точку коду.

  28. Код, який перекодує з UTF-16 або UTF-32 з ведучими BOM в UTF-8, порушується, якщо він ставить BOM на початку результуючого UTF-8. Це так нерозумно, що інженер повинен видалити повіки.

  29. Код, який передбачає, що CESU-8 є дійсним кодуванням UTF, є неправильним. Так само код, який вважає, що кодування U + 0000, як "\xC0\x80"і UTF-8, порушений і неправильний. Ці хлопці також заслуговують на лікування повік.

  30. Код, який передбачає, що символи як >завжди вказують праворуч і <завжди вказують ліворуч, помиляються - тому що вони насправді цього не роблять.

  31. Код, який передбачає, що ви спочатку виведете символ, Xа потім символ Y, що вони відображатимуться як XYнеправильні. Іноді цього не роблять.

  32. Код, який передбачає, що ASCII достатньо хороший для правильного написання англійської мови, є дурним, недалекоглядним, неграмотним, зламаним, злим і неправильним. Геть головою! Якщо це здається занадто крайнім, ми можемо йти на компроміс: відтепер вони можуть набирати лише великим пальцем ноги з однієї ноги. (Решта буде проклеєна каналом.)

  33. Код, який передбачає, що всі \p{Math}кодові точки є видимими символами, неправильний.

  34. Код, який передбачає, що \wмістить лише літери, цифри та підкреслення неправильно.

  35. Код , який передбачає , що ^і ~розділові знаки неправильно.

  36. Код, який передбачає, що üє умлаут, неправильний.

  37. Код, який вважає, що такі речі, як містять будь-які літери, є неправильними.

  38. Кодекс, який вважає \p{InLatin}, такий самий, як і \p{Latin}він жорстоко порушений.

  39. Кодекс, який вважає, що \p{InLatin}майже завжди корисний, майже напевно помиляється.

  40. Код, який вважає, що поданий $FIRST_LETTERяк перша буква в деякому алфавіті і $LAST_LETTERяк остання літера в тому ж алфавіті, який [${FIRST_LETTER}-${LAST_LETTER}]має будь-яке значення, майже завжди є повним ламаним, неправильним і безглуздим.

  41. Код, який вважає, що чиєсь ім'я може містити лише певні символи, є дурним, образливим та неправильним.

  42. Код, який намагається звести Unicode до ASCII, не є просто помилковим, його винуватцю більше ніколи не дозволяти працювати з програмуванням. Період. Я навіть не впевнений, що їх навіть дозволяють побачити ще раз, оскільки це, очевидно, не принесло їм нічого хорошого.

  43. Код, який вважає, що існує якийсь спосіб зробити вигляд, що кодування текстових файлів не існують, порушений і небезпечний. Можливо, також висунути інше око теж.

  44. Код, який перетворює невідомі символи ?, зламаний, нерозумний, розумний і суперечить стандартній рекомендації, яка говорить НЕ ЧАЙТЕ ТАК! RTFM, чому б ні.

  45. Код, який вважає, що може надійно здогадатися, що кодування немаркованого текстового файлу є винним у фатальній меланжі хабрі і наївності, яку виправить лише блискавка від Зевса.

  46. Код, який вважає, що ви можете використовувати 🐪 printfширину для прокладки та виправдання даних Unicode, зламаний і неправильний.

  47. Код, який вважає, що після успішного створення файлу за вказаним іменем, що при запуску lsабо readdirв його додаючому каталозі ви дійсно знайдете, що файл із ім'ям, під яким ви його створили, є помилковим, зламаним та неправильним. Перестаньте дивуватися цим!

  48. Код, який вважає, що кодування UTF-16 є фіксованою шириною, є дурним, зламаним та неправильним. Анулюють ліцензію на програмування.

  49. Код, який розглядає кодові точки з однієї площини, а інша, ніж будь-яка інша площина, ipso facto зламаний і неправильний. Поверніться до школи.

  50. Код, який вважає, що подібні речі /s/iможуть збігатися "S"або "s"порушуватись і неправильно. Ви були б здивовані.

  51. Код, який використовується \PM\pM*для пошуку кластерів графем замість використання \X, порушений і неправильний.

  52. Людей, які хочуть повернутися до світу ASCII, слід від щирого серця заохочувати це робити, і на честь їхнього славного оновлення їм слід надати безкоштовно електричну машинку з ручним набором для всіх їх потреб у введенні даних. Повідомлення, надіслані їм, слід надсилати телеграфом із 40 символами на рядок та доставляти вручну кур’єром. СТОП.


😱 𝕾 𝖀 𝕸 𝕸 𝕬 𝕽 𝖄 😱


Я не знаю, наскільки можна отримати більше "Unicode за замовчуванням у can", ніж те, що я написав. Ну, так, я так: ви повинні використовувати Unicode::Collateі Unicode::LineBreakтеж. І, мабуть, більше.

Як ви бачите, є занадто багато Unicode речей , які ви дійсно дійсно повинні турбуватися про для там коли - або існує така річ , як « по умовчанням в Unicode».

Що ви збираєтесь виявити, як ми це робили ще в 5,8 ст., Що нав’язувати всі ці речі коду, який не був розроблений з самого початку, просто неможливо. Ваш добронамерений егоїзм просто зламав увесь світ.

І навіть після того, як ви це зробите, все ще залишаються критичні питання, які потребують великої думки, щоб правильно. Немає комутатора, який можна перевернути. Тут не вистачить нічого, крім мозку, я маю на увазі справжній мозок . Ви маєте багато чого навчитися. Модулюючи відступ до машинки з ручним написом, ви просто не можете сподіватися прокрастися через незнання. Це 21 століття, і ви не можете побажати Юнікоду відволіктись навмисним незнанням.

Ви повинні це навчитися. Період. Ніколи не буде так просто, що "все просто працює", тому що це гарантуватиме, що багато речей не спрацює - що скасовує припущення про те, що коли-небудь може бути спосіб "змусити все працювати".

Можливо, ви зможете отримати кілька розумних стандартних налаштувань за дуже мало та дуже обмежені операції, але не без думок про речі набагато більше, ніж я думаю, у вас є.

Як лише один приклад, канонічне упорядкування буде викликати справжні головні болі. 😭 "\x{F5}" 'õ' , "o\x{303}" 'õ' , "o\x{303}\x{304}" 'ȭ' і"o\x{304}\x{303}" 'ō̃' всі повинні відповідати "õ" , але як у світі ви збираєтесь це робити? Це важче, ніж це виглядає, але це те, що потрібно враховувати. 💣

Якщо є одна річ, яку я знаю про Perl, це те, що роблять і не роблять її біти Unicode, і я вам це обіцяю: “̲ᴛ̲ʜ̲ᴇ̲ʀ̲ᴇ̲ ̲ɪ̲s̲ ̲ɴ̲ᴏ̲ ̲U̲ɴ̲ɪ̲ᴄ̲ᴏ̲ᴅ̲ᴇ̲ ̲ᴍ̲ᴀ̲ɢ̲ɪ̲ᴄ̲ ̲ʙ̲ᴜ̲ʟ̲ʟ̲ᴇ̲ᴛ̲ ̲” 😞

Ви не можете просто змінити параметри за замовчуванням і отримати плавне плавання. Це правда, що я бігаю 🐪 зPERL_UNICODE встановленим параметром "SA", але це все, і навіть це в основному для матеріалів командного рядка. Для справжньої роботи я проходжу всі багато кроків, описаних вище, і роблю це дуже, ** дуже ** ретельно.


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


56
Ніби Шерм Пендлі вказував: "Все!". Якщо сьогодні я напишу щось нове, UTF-8 повинен бути найпростішим способом зробити справи. Це не так. Ваша котельня підтверджує це. Не у всіх є такі знання, щоб перетворити стільки перешкод на правильні позиції. Вибачте, у мене був довгий і важкий день, тому я завтра коментую головний запис більше із прикладами.
wk

17
Один з висновків повинен бути очевидним, читаючи список вище: Не складайте справи. Просто ні. Колись. Обчислювально дорогі та з семантикою, що вирішально залежать від того, що б це не було, "локал" намагається ідентифікувати невдало.
Тім Брей

72
Чи я єдиний, хто вважає іронічним те, що ця публікація від tchrist робить настільки дико різною на FF / Chrome / IE / Opera, десь до точки нерозбірливості?
пошкодження

15
У той час як мені взагалі подобається посада, і я висловлюю заяву, одна річ клопотів із мене. Існує багато "коду, який ... порушений". Хоча я не заперечую з твердженням, я думаю, було б добре показати зламаність. Таким чином він би перейшов (цю частину відповіді) від зусиль, до освіти.

36
@xenoterracide Ні, я не використовував навмисно проблемні кодові точки; це змова змусити вас встановити надзвичайно дивовижний шрифт Symbola Джорджа Дороса , який охоплює Unicode 6.0. 😈 @depesz Тут немає місця, щоб пояснити, чому кожен розбитий припущення є неправильним. @leonbloy Багато та багато цього стосується Unicode взагалі, а не лише Perl. Частина цього матеріалу може з’явитися у 4-му виданні «Програмування Perl», яке вийде у жовтні. 🎃 У мене залишився місяць ✍ над цим працювати, і Unicode є ᴍᴇɢᴀ там;
реджекси

96

Існує два етапи обробки тексту Unicode. Перший - "як я можу ввести його та вивести його, не втрачаючи інформації". Друга - "як я поводжусь з текстом відповідно до місцевих мовних умов".

Повідомлення tchrist охоплює обидва, але друга частина - це те, звідки походить 99% тексту в його публікації. Більшість програм навіть не обробляють I / O правильно, тому важливо розуміти, що перед тим, як почати турбуватися про нормалізацію та співставлення.

Цей пост має на меті вирішити цю першу проблему

Коли ви читаєте дані в Perl, то все одно, що це кодування. Він виділяє деяку пам’ять і приховує байти туди. Якщо ви говоритеprint $str , він просто виблискує ці байти до вашого терміналу, який, ймовірно, встановлений, щоб припустити, що все, що йому написано, є UTF-8, і ваш текст відображається.

Чудовий.

За винятком, це не так. Якщо ви спробуєте ставитися до даних як до тексту, ви побачите, що відбувається щось погане. Вам не потрібно йти далі, lengthщоб побачити, що те, що Perl думає про вашу струну, і що ви думаєте про свою струну, не погоджуються. Напишіть однолінійку типу: perl -E 'while(<>){ chomp; say length }'та введіть文字化け і отримаєте 12 ... не правильна відповідь, 4.

Це тому, що Perl припускає, що ваш рядок не є текстом. Ви повинні сказати йому, що це текст, перш ніж він дасть правильну відповідь.

Це досить просто; Модуль кодування має функції для цього. Загальною точкою входу є Encode::decode(абоuse Encode qw(decode) , звичайно,). Ця функція бере деякий рядок із зовнішнього світу (те, що ми будемо називати "октетами", хитромудрий спосіб сказати "8-бітні байти") і перетворить його в текст, який Perl зрозуміє. Перший аргумент - це ім'я кодування символів, наприклад "UTF-8" або "ASCII" або "EUC-JP". Другий аргумент - рядок. Повернене значення - скаляр Perl, що містить текст.

(Є також Encode::decode_utf8, що передбачає UTF-8 для кодування.)

Якщо ми перепишемо наш однолінійний:

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

Набираємо 文字 化 け і отримуємо «4» в результаті. Успіх.

Це, саме там, є вирішенням 99% проблем Unicode в Perl.

Ключ полягає в тому, що коли будь-який текст надходить у вашу програму, ви повинні розшифрувати його. Інтернет не може передавати символи. Файли не можуть зберігати символи. У вашій базі даних немає символів. Є лише октети, і ви не можете розглядати октети як символи в Perl. Ви повинні розшифрувати закодовані октети в символи Perl за допомогою модуля Encode.

Інша половина проблеми - це виведення даних із вашої програми. Це легко зробити; Ви просто скажіть use Encode qw(encode), вирішіть, якою буде кодування ваших даних (UTF-8 до терміналів, які розуміють UTF-8, UTF-16 для файлів у Windows тощо), а потім виведіть результат, encode($encoding, $data)а не просто виведіть $data.

Ця операція перетворює символи Perl, над якими працює ваша програма, в октети, які можуть використовуватися зовнішнім світом. Було б набагато простіше, якби ми могли просто відправляти персонажів через Інтернет або до наших терміналів, але ми не можемо: лише октети. Отже, ми повинні перетворити символи в октети, інакше результати не визначені.

Підсумовуючи: кодуйте всі результати та декодуйте всі входи.

Зараз ми поговоримо про три питання, які роблять це трохи складним. Перша - це бібліотеки. Чи правильно вони обробляють текст? Відповідь ... вони намагаються. Якщо ви завантажите веб-сторінку, LWP поверне результат як текст. Якщо ви викликаєте правильний метод за результатом, тобто (а це трапляється decoded_content, ніcontent , це просто потік октету, який він отримав від сервера.) Драйвери бази даних можуть бути помилковими; якщо ви використовуєте DBD :: SQLite тільки з Perl, це вийде, але якщо якийсь інший інструмент помістив текст, який зберігається як якесь кодування, крім UTF-8 у вашій базі даних ... ну ... це не буде правильно оброблятися поки ви не напишете код, щоб правильно його обробити.

Виведення даних, як правило, простіше, але якщо ви бачите "широкий символ у друку", то ви знаєте, що ви дещо псуєте кодування. Це попередження означає "ей, ти намагаєшся просочити персонажів Perl у зовнішній світ, і це не має ніякого сенсу". Здається, що ваша програма працює (тому що інший кінець зазвичай правильно обробляє сирої символи Perl), але вона дуже зламана і може перестати працювати в будь-який момент. Виправте це з явним Encode::encode!

Друга проблема - це кодований вихідним кодом UTF-8. Якщо ви не скажете use utf8вгорі кожного файлу, Perl не припустить, що ваш вихідний код - UTF-8. Це означає, що кожного разу, коли ви говорите щось на кшталт my $var = 'ほげ', ви вводите сміття у свою програму, яка повністю жахливо зламає все. Вам не потрібно "використовувати utf8", але якщо цього не зробити, ви не повинні використовувати жодні символи , що не належать до ASCII, у вашій програмі.

Третя проблема - як Perl поводиться з минулим. Давним-давно не існувало такого поняття, як Unicode, і Перл припускав, що все це текст латиниці-1 або двійковий. Отже, коли дані надходять у вашу програму, і ви починаєте трактувати їх як текст, Perl розглядає кожен октет як символ латиниці-1. Ось чому, коли ми запитували про довжину "文字 化 け", ми отримали 12. Перл припустив, що ми працюємо на латинській строці "æååã" (це 12 символів, частина з яких не друкується).

Це називається "неявне оновлення", і це цілком розумно робити, але це не те, що ви хочете, якщо ваш текст не є латинським-1. Ось чому важливо чітко розшифрувати введення: якщо ви цього не зробите, Perl зробить це, і це може зробити це неправильно.

Люди стикаються з проблемою, коли половина їх даних є належним символьним рядком, а частина - ще двійковою. Perl інтерпретує частину, яка все ще є двійковою, як ніби це текст латиниці 1, а потім поєднує її з правильними даними символів. Це зробить вигляд, що поводження з персонажами правильно порушило вашу програму, але насправді ви її просто не виправили.

Ось приклад: у вас є програма, яка читає текстовий файл, закодований UTF-8, ви вводите Unicode PILE OF POOдо кожного рядка і ви роздруковуєте його. Ви пишете це так:

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

А потім запустіть деякі закодовані UTF-8 дані, наприклад:

perl poo.pl input-data.txt

Він друкує дані UTF-8 з пулом у кінці кожного рядка. Ідеально, моя програма працює!

Але ні, ви просто робите бінарне з'єднання. Ви читаєте октети з файлу, видаляєте \nchomp, а потім торкаєтесь байтів у зображенні PILE OF POOсимволу UTF-8 . Переглянувши програму для декодування даних з файлу та кодування виводу, ви помітите, що ви отримуєте сміття ("ð ©") замість poo. Це призведе до того, що ви вважаєте, що розшифрувати вхідний файл - це неправильно. Це не.

Проблема полягає в тому, що поось неявно модернізується як латинь-1. Якщо ви use utf8зробите буквальний текст замість двійкового, то він спрацює знову!

(Це проблема номер один, яку я бачу, допомагаючи людям з Unicode. Вони зробили частку правильно, і це порушило їхню програму. Ось що сумно в невизначених результатах: ви можете мати робочу програму тривалий час, але коли ви почнете її ремонтувати, Не хвилюйтесь; якщо ви додаєте в програму операції кодування / декодування, і вона порушується, це просто означає, що вам доведеться виконати більше роботи. Наступного разу, коли ви проектуватимете Unicode на увазі з самого початку, це буде набагато простіше!)

Це дійсно все, що вам потрібно знати про Perl та Unicode. Якщо ви скажете Perl, що ваші дані, він має найкращу підтримку Unicode серед усіх популярних мов програмування. Якщо ви припускаєте, що він буде магічно знати, який тип тексту ви його подаєте, тоді ви збираєтеся безповоротно виправити свої дані. Тільки тому, що ваша програма працює сьогодні на вашому терміналі UTF-8, це не означає, що вона працюватиме завтра на закодованому файлом UTF-16. Тож зробіть це безпечним зараз і вбережіть головний біль від збиття даних користувачів!

Легкою частиною обробки Unicode є кодування виводу та декодування вводу. Важкою частиною є пошук усіх ваших вхідних та вихідних даних та визначення того, що це кодування. Але саме тому ви отримуєте великі гроші :)


Принцип пояснений добре, але практичний підхід для вводу-виводу відсутній. Явне використання Encodeмодуля є виснажливим і схильним до помилок, і читання коду, що стосується вводу-виводу, дійсно болісне. Шари вводу / виводу забезпечують рішення, оскільки вони прозоро кодують і декодують, де це необхідно. openі binmodeдозволити їх конкретизацію, а прагма openвстановлює параметри за замовчуванням, як рекомендує tchrist у своїй відповіді.
Palec

48

Ми всі згодні з тим, що це складна проблема з багатьох причин, але саме ця причина намагається полегшити всім.

Існує останній модуль на CPAN, utf8 :: all , який намагається "включити Unicode. Все це".

Як було зазначено, ви не можете магічно змусити всю систему (зовнішні програми, зовнішні веб-запити тощо) також використовувати Unicode, але ми можемо працювати разом, щоб зробити розумні інструменти, які полегшують спільні проблеми. Це причина, що ми програмісти.

Якщо utf8 :: всі не роблять те, що ви думаєте, що слід, давайте вдосконалимо його, щоб зробити його кращим. Або давайте зробимо додаткові інструменти, які разом можуть максимально задовольнити різні потреби людей.

`


5
Я бачу багато можливостей для вдосконалення цитованого utf8::allмодуля. Це було написано перед unicode_stringsфункцією, яка Fɪɴᴀʟʟʏ ᴀɴᴅ ᴀᴛ Lᴏɴɢ Lᴀsᴛ фіксує регекси, щоб мати /uна них. Я не впевнений, що це створює виняток щодо помилок кодування, і це справді ви повинні мати. Він не завантажується в use charnames ":full"прагму, яка ще не завантажена. Він не попереджає про [a-z]та такі printfстрокові ширини, використовуючи \nзамість цього, \Rа не .замість цього \X, але, можливо, це більше Perl::Criticпитання. Якби це я, я додавав би і виходив.
tchrist

13
@tchrist Трекер випусків для utf8 :: все тут. github.com/doherty/utf8-all/isissue Вони б хотіли почути ваші пропозиції.
Шверн

4
@Schwern: Так, але не соромтеся грабіти і щипатись від речей, які я написав тут. Якщо чесно, я все ще відчуваю / вивчаю, що можна зробити проти того, що слід робити, і де. Ось хороший приклад від розвантаження сортування: unichars -gs '/(?=\P{Ll})\p{Lower}|(?=\P{Lu})\p{Upper}/x' | ucsort --upper | cat -n | less -r. Аналогічно, і такі невеликі кроки попередньої обробки, як ... | ucsort --upper --preprocess='s/(\d+)/sprintf "%#012d", $1/ge'насправді, теж можуть бути приємними, і я не хотів би приймати за них рішення інших. Я все ще будую панель інструментів Unicode .
tchrist

35

Я думаю, ви неправильно зрозуміли Unicode та його стосунки до Perl. Незалежно від того, яким чином ви зберігаєте дані, Unicode, ISO-8859-1 або багато інших речей, ваша програма повинна знати, як інтерпретувати байти, які вона отримує, як введення (декодування) та як представляти інформацію, яку вона хоче виводити (кодування ). Помиліть цю інтерпретацію неправильно, і ви отримаєте дані. У вашій програмі немає якоїсь магічної установки за замовчуванням, яка б розповіла, як потрібно діяти поза вашою програмою, як діяти.

Ви думаєте, що це важко, швидше за все, тому що ви звикли до всього, що є ASCII. Все, про що ви повинні були думати, було просто ігноровано мовою програмування та всіма речами, з якими вона мала взаємодіяти. Якби все не використовувало нічого, крім UTF-8, і у вас не було вибору, то UTF-8 було б так само просто. Але не все використовується UTF-8. Наприклад, ви не хочете, щоб ваша вхідна ручка думала, що вона отримує октети UTF-8, якщо вона насправді не є, і ви не хочете, щоб вихідні ручки були UTF-8, якщо річ, що читається з них, може обробляти UTF-8 . У Perl немає ніякого способу пізнати ці речі. Ось чому ви програміст.

Я не думаю, що Unicode в Perl 5 занадто складний. Я думаю, що це страшно, і люди уникають цього. Є різниця. З цією метою я поставив Unicode в Learning Perl, 6-е видання , і є багато матеріалів Unicode в Ефективному програмуванні Perl . Ви повинні витратити час, щоб вивчити та зрозуміти Unicode та як він працює. Ви не зможете ефективно використовувати його інакше.


3
Я думаю, у вас є пункт: це страшно. Чи має бути? Для мене це благословення Unicode, використання його в Perl5 не є (я не вважаю, що щось є ASCII, моїй рідній мові потрібно принаймні iso8859-4). Я встановив Rakudo, і все, що я спробував з UTF-8 (у цій обмеженій пісочниці), працював із коробки. Я щось пропустив? Я наголошую це ще раз: добре налаштувати підтримку Unicode, але в більшості випадків це не потрібно. Щоб позбавити страху від теми, один із способів - кожен читає багато, щоб зрозуміти внутрішнє. Інше: у нас є спеціальна прагма, яка use utf8_everywhereробить людей щасливими. Чому не останній?
wk

3
Я все ще думаю, що ви пропускаєте суть. Що спрацювало? Вам не потрібно розуміти внутрішніх справ. Вам потрібно зрозуміти зовнішні та як обробляти рядки, що мають різні кодування та різні зображення одних і тих же символів. Прочитайте пораду Тома ще раз. Більшість того, що він каже, я думаю, що ви знайдете, що Ракудо не справляється за вас.
Брайан d foy

1
@wk: ще раз прочитайте відповідь Ренді. Він уже сказав вам, що таке обмеження.
Брайан d foy

2
@brian d foy: я думаю, що це обмеження добре, як каже тріхріст, немає чарівної кулі для кожного аспекту (зізнаюся: я не бачив більшості з них, перш ніж задавати це питання тут). Таким чином, коли ми покриваємо багато основних речей таким чином, як utf8 :: all, немає необхідності в тому, щоб кожен будував власну величезну котельну плиту лише для того, щоб отримати основи керування utf8 для роботи. Маючи на увазі "зовсім не страх", я маю на увазі: кожен може розпочати свої проекти, знаючи, що основи охоплені. Так, ви маєте рацію, проблем ще багато. Але коли починати простіше, у нас буде більше людей, які беруть участь у їх вирішенні. IMHO
wk

1
@wk - єдине "неправильне" з "utf8: all" або "uni :: perl - це лише одне - їх немає в CORE - тому всі повинні встановити його з CPAN. І якщо ви думаєте, що це не велике угода - переосмислите будь ласка - так, легше використовувати utf8 з допоміжним модулем. Без нього в CORE perl все ще є підтримка unicode - але набагато-набагато складніше. І це неправильно.
jm666

28

Читаючи цю тему, у мене часто виникає враження, що люди використовують " UTF-8 " як синонім " Unicode ". Будь ласка, зробіть різницю між "Кодовими точками" Unicode, які є збільшеним родичем коду ASCII та різними "кодуваннями" Unicode. І є декілька з них, серед яких UTF-8, UTF-16 та UTF-32 є поточними, а ще декілька - застарілими.

Будь ласка, UTF-8 (як і всі інші кодування ) існує і має значення лише для введення або виводу. Внутрішньо, починаючи з Perl 5.8.1, всі рядки зберігаються як Unicode "Кодові точки". Щоправда, ви повинні включити деякі функції, як милувались раніше.


19
Я погоджуюсь, що люди занадто часто плутають Uɴɪᴄᴏᴅᴇ з UTF-8⧸16⧸32, але це принципово і критично неправда, що U just - це лише деякий збільшений набір символів щодо ᴀsᴄɪɪ. Щонайбільше , це не що інше, як просто ɪsᴏ ‑ 10646 . Uɴɪᴄᴏᴅᴇ включає в себе набагато більше : правила зіставлення, складання регістрів, форми нормалізації, кластери графеми, розбиття слів і рядків, скрипти, числові еквіваленти, ширини, двонаправленість, варіанти гліфів, контекстна поведінка, локали, регекси, комбінування класів, 100-ти властивості та & набагато більше‼
tchrist

15
@tchrist: перший крок - отримати дані у свою програму та вийти у зовнішній світ, не переробляючи їх. тоді ви можете турбуватися про зібрання, складання корпусу, варіанти гліфів тощо.
jrockway

7
Я погоджуюсь, першочерговим завданням має стати отримання perl, щоб не вносити або виводити сміття. Мені б хотілося, щоб був модуль або прагма, яка могла б втілити наступну вигадану розмову: "- Шановний Perl. Для цієї програми всі введення та виведення будуть виключно UTF-8. Чи можете ви, будь ласка, не втратити мої дані? - Так ви говорите лише UFT-8. Ви впевнені? - Так. - Дійсно, дуже впевнений? - Добре тоді."
хловдал

10

Існує по-справжньому жахливе кількість старовинного коду там у дикій природі, значна частина його у вигляді загальних модулів CPAN. Я виявив, що я повинен бути дуже обережним, щоб увімкнути Unicode, якщо я використовую зовнішні модулі, на які це може вплинути, і все ще намагаюся виявити і виправити деякі помилки, пов’язані з Unicode, у кількох сценаріях Perl, які я регулярно використовую (зокрема, iTiVo виходить з ладу погано у всьому, що не є 7-бітним ASCII через проблеми перекодування).


Я мав на увазі використовувати -Cпараметр, щоб переконатися, що Perl знаходиться на тій же самій сторінці, що і я розумний Unicode, тому що я продовжую його вирішувати використовувати ISO 8859/1 замість Unicode, хоча я чітко налаштований $LANGі $LC_ALLправильно. (Це насправді може відображати помилки в бібліотеках локальних платформ.) Що б це не було, мені дуже дратує те, що я не можу використовувати iTivo для програм з акцентами в них, оскільки сценарії Perl, які виконують роботу, перепадають з помилками перетворення.
geekosaur

3
Самотня -Cбез варіантів - баггі та схильність до помилок . Ви ламаєте світ. Встановіть PERL5OPTEnviriable на, -Cі ви побачите, що я маю на увазі. Ми спробували цей шлях ще в версії 5.8, і це було катастрофою. Ви просто не можете і не повинні повідомляти програмам, які цього не очікують, що зараз вони мають справу з Unicode, подобається їм це чи ні. Також є проблеми безпеки. Як мінімум, все, що print while <>буде порушено, якщо передаються двійкові дані. Так само буде і весь код бази даних. Це жахлива ідея.
tchrist

1
Я говорив загалом, власне, не конкретно -Cбез варіантів. Конкретне виклик, з яким я працював, було -CSDA. Це сказало, що я довго тримався 5.8.x (привіт MacPorts ...), тож, можливо, це було частиною цього.
geekosaur

1
Я запускаю з PERL_UNICODE, встановленого на SA. Ви НЕ МОЖЕТЕ встановити його на D.
tchrist

@tchrist: Деякий Perl varmint розміщував код із зазначенням -CSDA та PERL_UNICODE = використання SDA . Будь ласка, використовуйте свій вплив у громаді. Його треба зупинити!
Ешлі

1

Вам слід включити функцію рядків Unicode, і це типово, якщо ви використовуєте v5.14;

Вам не слід використовувати ідентифікатори unicode esp. для закордонного коду через utf8, оскільки вони є небезпечними в perl5, тільки cperl отримав це право. Див., Наприклад, http://perl11.org/blog/unicode-identifiers.html

Щодо utf8 для ваших файлових файлів / потоків: Вам потрібно вирішити самостійно кодування зовнішніх даних. Бібліотека цього не може знати, і оскільки навіть libc не підтримує utf8, належні дані utf8 рідкісні. Більше wtf8, вікна відхилення utf8 навколо.

BTW: Moose насправді не "Modern Perl", вони просто захопили назву. Moose - це ідеальний постмодерністський стиль Ларрі Уолл, змішаний із стилем Bjarne Stroustrup, все йде з еклектичною аберацією власного синтаксису perl6, наприклад, використовуючи рядки для змінних імен, синтаксис жахливих полів та дуже незрілу наївну реалізацію, яка на 10 разів повільніше, ніж належна реалізація. cperl і perl6 - справжні сучасні perls, де форма слідує за функцією, а реалізація скорочується та оптимізується.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.