/ / Чому розшифровка "& euro;" до "€" також перетворює "é" у "Ã ©" у виході? - perl, utf-8, кодування символів

Чому декодування "& euro;" до "€" також перетворює "é" на "Ã ©" на виході? - perl, utf-8, кодування символів

Я новачок в сценаріях Perl, і я стикаюся з деякими проблемами в розшифровці рядка:

use HTML::Entities;
my $string="Rémunération   €";
$string=decode_entitie($string);
print "$string";

Отриманий результат виглядає так Rémunération €, коли це має виглядати Rémunération €.

Чи може хто-небудь, будь ласка, допоможіть мені з цим?

Відповіді:

8 для відповіді № 1

Якщо ви користуєтеся цією версією коду (з друком в decode_entities фіксований, строгий режим і попередження увімкнено та додатково print додано) в терміналі:

use strict;
use warnings;
use HTML::Entities;
my $string="Rémunération   €";
print "$stringn";
$string=decode_entities($string);
print "$stringn";

Ви повинні побачити такий вихід:

Rémunération   €
Wide character in print at test.pl line 7.
Rémunération   €

Що відбувається - це наступний ланцюжок подій:

  1. Ваш код написано utf-8, але не майте use utf8; в ньому, тому Perl аналізує ваш вихідний код (і, зокрема, будь-які рядкові літерали в ньому) байт за байтом. Таким чином, рядок буквальний "é" аналізується як двозначний рядок, тому що кодування utf-8 é займає два байти.

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

    Отже, коли ти робиш print "é"; Perl думає, що ви "друкуєте двосимвольну рядок у байтовому режимі і виписуєте два байти, які просто трапляються для кодування utf-8 кодування одного символу é.

  3. Однак, коли ви запускаєте рядок наскрізь decode_entities(), він розшифровує € у фактичний Unicode символу, який не вміщується всередині одного байта.

  4. Коли ви намагаєтеся надрукувати отриманий рядок, Perl помічає "широкий" характер. Він не може друкувати його як єдиний байт, тому замість цього він повертається до кодування весь рядок як utf-8 (і надсилає попередження, якщо вони увімкнено, як слід). Але це викликає és (які були вже закодовані, оскільки Perl ніколи їх не розшифровував під час розбору вашого коду), щоб отримати подвійне кодування UTF8, створюючи моджибаке вихід, який ви бачите.

Просте виправлення - додати use utf8; до вашого коду, а також встановити всі файлові файли (в тому числі STDIN / STDOUT / STDERR) до режиму utf-8 за замовчуванням, наприклад подобається це:

use utf8;
use open qw(:std :utf8);

Якщо ті рядки були попередньо випробуваним сценарієм вище, отриманий результат повинен бути:

Rémunération   €
Rémunération   €