¿Por qué mi Perl no funciona bien con Unicode?

¿Por qué mi Perl no funciona bien con Unicode?

En mi nueva instalación de Arch, perlno parece funcionar bien con Unicode. Por ejemplo, dado este archivo de entrada:

ελα ρε
王小红

Este comando debería darme los dos últimos caracteres de cada línea:

$ perl -CIO -pe 's/.*(..)$/$1/' file
ε
º¢

Sin embargo, como puedes ver arriba, entiendo un galimatías. La salida correcta es:

ρε
小红

Sé que mi terminal ( gnome-terminator) admite UTF-8 ya que ambos funcionan como se esperaba:

$ cat file
ελα ρε
王小红
$ perl -pe '' file
ελα ρε
王小红

Desafortunadamente, sin -CIO, perltampoco maneja los archivos correctamente:

$ perl -pe 's/.*(..)$/$1/' file
ε
��

Tampoco debería ser un problema local:

$ locale
LANG=en_US.UTF-8
LC_CTYPE="en_US.UTF-8"
LC_NUMERIC="en_US.UTF-8"
LC_TIME="en_US.UTF-8"
LC_COLLATE="en_US.UTF-8"
LC_MONETARY="en_US.UTF-8"
LC_MESSAGES="en_US.UTF-8"
LC_PAPER="en_US.UTF-8"
LC_NAME="en_US.UTF-8"
LC_ADDRESS="en_US.UTF-8"
LC_TELEPHONE="en_US.UTF-8"
LC_MEASUREMENT="en_US.UTF-8"
LC_IDENTIFICATION="en_US.UTF-8"
LC_ALL=

Supongo que necesito instalar algunos paquetes de Perl, pero no sé cuáles. Alguna información relevante:

$ perl --version | grep subversion
This is perl 5, version 22, subversion 0 (v5.22.0) built for x86_64-linux-thread-multi

$ pacman -Qs unicode
local/fribidi 0.19.7-1
    A Free Implementation of the Unicode Bidirectional Algorithm
local/icu 55.1-1
    International Components for Unicode library
local/libunistring 0.9.6-1
    Library for manipulating Unicode strings and C strings
local/perl 5.22.0-1 (base)
    A highly capable, feature-rich programming language
local/perl-unicode-stringprep 1.105-1
    Preparation of Internationalized Strings (RFC 3454)
local/perl-unicode-utf8simple 1.06-5
    Conversions to/from UTF8 from/to characterse
local/ttf-arphic-uming 0.2.20080216.1-5
    CJK Unicode font Ming style

¿Cómo puedo hacer que mi instalación de Perl funcione bien con Unicode?

Respuesta1

El problema que estás describiendo es el comportamiento estándar en los sistemas que probé. Iy Oafecta stdin y stdout, por lo que esto debería funcionar:

→ cat data | perl -CIO -pe 's/.*(..)$/$1/'
ρε
小红

Mientras que esto podría no:

→ perl -CIO -pe 's/.*(..)$/$1/' data
ε
º¢

Haydos opciones más paraperl -Cque producen el comportamiento deseado.

i     8   UTF-8 is the default PerlIO layer for input streams
o    16   UTF-8 is the default PerlIO layer for output streams

Lo que básicamente significa que para Perl, use un formulario de apertura de archivo:

open(F, "<:utf8", "data");

o puedes usar perl -CSDcual es una abreviatura deperl -CIOEio

S     7   I + O + E
D    24   i + o

Entonces obtienes

→ perl -CSD -pe 's/.*(..)$/$1/' data
ρε
小红

Si la PERLIOvariable de entorno está configurada e incluye, :utf8este comportamiento también estaría habilitado.

Parece que el comportamiento predeterminado perltampoco se puede modificar en el momento de la configuración/compilación (comentario de Cuonglm a continuación). Arch ciertamente noestablecer cualquier cosa.Dudo que los paquetes de Debian Perl modifiquen el comportamiento predeterminado.

Respuesta2

Eso no es un problema del sistema sino del perlmismo.

-CIOsolo configure la codificación UTF-8 en STDINy STDOUT, dos de los tres identificadores de archivos predefinidos ( también perltiene -Efor ).STDERR

Cuando usas:

perl -CIO -pe 's/.*(..)$/$1/' file

perlUtilice el operador de diamante <>para procesar el archivo. Desde cuando el operador de diamantes <>usóabierto (con forma de dos argumentos)para crear un nuevo identificador de archivo para cada archivo desde la línea de comando, estos identificadores de archivo no se verán afectados por la codificación UTF-8 que configuró STDINy STDOUT.

Entonces, puedes pasar el contenido del archivo a perltravés de su entrada estándar y funcionará:

perl -CIO -pe 's/.*(..)$/$1/' <file

Para otras opciones ver@La respuesta de Matt.


En caso de que desee perlutilizar su configuración regional para la capa de codificación predeterminada, puede utilizar:

perl -Mopen=:locale -pe 's/.*(..)$/$1/' file

Cuando utilice PERLIOpara configurar la capa de codificación, debeusar :encoding(uf8)en lugar de:utf8.

El uso :utf8omite el paso de codificación y puede causar problemas al leer secuencias de bytes UTF-8 no válidas y provocar problemas de seguridad.

información relacionada