Por que meu Perl não é legal com o Unicode?

4

Na minha nova instalação do Arch, perl parece não funcionar bem com o Unicode. Por exemplo, dado este arquivo de entrada:

ελα ρε
王小红

Este comando deve me fornecer os dois últimos caracteres de cada linha:

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

No entanto, como você pode ver acima, eu fico rabugento. A saída correta é:

ρε
小红

Eu sei que meu terminal ( gnome-terminator ) suporta UTF-8, já que ambos funcionam como esperado:

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

Infelizmente, sem -CIO , perl não lida corretamente com os arquivos:

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

Também não deve ser um problema de localidade:

$ 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=

Suponho que preciso instalar alguns pacotes Perl, mas não sei quais. Alguma informação 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

Como posso fazer com que minha instalação do perl funcione com o Unicode?

    
por terdon 05.11.2015 / 19:10

2 respostas

6

O problema que você está descrevendo é o comportamento padrão nos sistemas em que eu testei. I e O afetam stdin e stdout, então isso deve funcionar:

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

Considerando que isso pode não acontecer:

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

Existem mais duas opções para perl -C que produzem seu comportamento desejado.

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

Que é basicamente dizendo para perl, use um formulário aberto de arquivo:

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

ou você pode usar perl -CSD , que é uma abreviação de perl -CIOEio

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

Então você começa

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

Se a variável de ambiente PERLIO estiver definida e incluir :utf8 , esse comportamento também será ativado.

Parece que o comportamento padrão para perl não é modificável no momento da configuração / compilação (comentário cuonglm abaixo). Arch certamente não definir qualquer coisa. Eu duvido debian perl pacotes modificaria o comportamento padrão.

    
por 06.11.2015 / 00:53
2

Isso não é um problema do sistema, mas o perl em si.

-CIO apenas definiu a codificação UTF-8 em STDIN e STDOUT , dois dos três perl filehandle predefinido (você também tem -E para STDERR ).

Quando você usa:

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

perl use o operador de diamante <> para processar o arquivo. Desde quando o operador de diamante <> usou aberto (com dois formulários de argumentos) para criar um novo filehandle para cada arquivo da linha de comando, esses filehandle não serão afetados pela codificação UTF-8 definida em STDIN e STDOUT .

Então, você pode passar o conteúdo do arquivo para perl através de seu stdin, e ele funcionará:

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

Para outras opções, consulte a @resposta de Matt .

Caso você queira que perl use sua localidade para a camada de codificação padrão, você pode usar:

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

Quando você usa PERLIO para definir a camada de codificação, deve use :encoding(uf8) em vez de :utf8 .

Usar :utf8 ignora a etapa de codificação e pode causar problemas ao ler seqüências inválidas de bytes UTF-8 e causar problemas de segurança.

    
por 06.11.2015 / 04:13

Tags