Na minha nova instalação do Arch, perl
não parece funcionar bem com 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, fico sem sentido. A saída correta é:
ρε
小红
Eu sei que meu terminal ( gnome-terminator
) suporta UTF-8, pois ambos funcionam conforme o esperado:
$ cat file
ελα ρε
王小红
$ perl -pe '' file
ελα ρε
王小红
Infelizmente, sem -CIO
, perl
também não lida com os arquivos corretamente:
$ 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=
Acho que preciso instalar alguns pacotes Perl, mas não sei quais. Algumas informações relevantes:
$ 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 Perl funcione bem com Unicode?
Responder1
O problema que você está descrevendo é o comportamento padrão nos sistemas em que testei. I
e O
afeta stdin e stdout, então isso deve funcionar:
→ cat data | perl -CIO -pe 's/.*(..)$/$1/'
ρε
小红
Considerando que isso pode não:
→ perl -CIO -pe 's/.*(..)$/$1/' data
ε
º¢
Hámais duas opções paraperl -C
que produzem o 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
O que basicamente quer dizer para Perl, use um formulário de abertura de arquivo:
open(F, "<:utf8", "data");
ou você pode usar perl -CSD
which é uma abreviação deperl -CIOEio
S 7 I + O + E
D 24 i + o
Então você consegue
→ perl -CSD -pe 's/.*(..)$/$1/' data
ρε
小红
Se a PERLIO
variável de ambiente estiver definida e incluir, :utf8
esse comportamento também será habilitado.
Parece que o comportamento padrão perl
também não pode ser modificado no momento da configuração/compilação (comentário cuonglm abaixo). Arch certamente nãodefinir qualquer coisa.Duvido que os pacotes debian perl modifiquem o comportamento padrão.
Responder2
Isso não é um problema do sistema, mas em perl
si.
-CIO
defina apenas a codificação UTF-8 STDIN
e STDOUT
, dois dos três perl
identificadores de arquivo predefinidos (você também tem -E
para ).STDERR
Quando você usa:
perl -CIO -pe 's/.*(..)$/$1/' file
perl
use o operador diamante <>
para processar o arquivo. Desde quando o operador de diamante <>
usouaberto (com forma de dois argumentos)para criar um novo identificador de arquivo para cada arquivo na linha de comando, esse identificador de arquivo não será afetado pela codificação UTF-8 definida em STDIN
e STDOUT
.
Então, você pode passar o conteúdo do arquivo perl
através de seu stdin, e ele funcionará:
perl -CIO -pe 's/.*(..)$/$1/' <file
Para outras opções consulteResposta de @Matt.
Caso queira perl
usar sua localidade para camada de codificação padrão, você pode usar:
perl -Mopen=:locale -pe 's/.*(..)$/$1/' file
Ao usar PERLIO
para definir a camada de codificação, você deveusar :encoding(uf8)
em vez de:utf8
.
Usar :utf8
ignora a etapa de codificação e pode causar problemas ao ler sequências de bytes UTF-8 inválidas e causar problemas de segurança.