Auf meiner neuen Arch-Installation perl
funktioniert Unicode anscheinend nicht einwandfrei. Als Beispiel sei diese Eingabedatei angegeben:
ελα ρε
王小红
Dieser Befehl sollte mir die letzten beiden Zeichen jeder Zeile geben:
$ perl -CIO -pe 's/.*(..)$/$1/' file
ε
º¢
Wie Sie oben sehen können, erhalte ich jedoch Kauderwelsch. Die korrekte Ausgabe lautet:
ρε
小红
Ich weiß, dass mein Terminal ( gnome-terminator
) UTF-8 unterstützt, da beide wie erwartet funktionieren:
$ cat file
ελα ρε
王小红
$ perl -pe '' file
ελα ρε
王小红
Leider geht auch ohne nicht richtig mit den Dateien um -CIO
:perl
$ perl -pe 's/.*(..)$/$1/' file
ε
��
Es sollte auch kein Gebietsschemaproblem sein:
$ 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=
Ich vermute, dass ich einige Perl-Pakete installieren muss, aber ich weiß nicht, welche. Einige relevante Informationen:
$ 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
Wie kann ich meine Perl-Installation so einrichten, dass sie gut mit Unicode funktioniert?
Antwort1
Bei dem von Ihnen beschriebenen Problem handelt es sich um ein Standardverhalten auf den Systemen, auf denen ich es getestet habe. I
Es O
betrifft stdin und stdout, also sollte Folgendes funktionieren:
→ cat data | perl -CIO -pe 's/.*(..)$/$1/'
ρε
小红
Dies könnte jedoch nicht der Fall sein:
→ perl -CIO -pe 's/.*(..)$/$1/' data
ε
º¢
Es gibtzwei weitere Optionen fürperl -C
die das gewünschte Verhalten hervorrufen.
i 8 UTF-8 is the default PerlIO layer for input streams
o 16 UTF-8 is the default PerlIO layer for output streams
Damit wird Perl im Wesentlichen gesagt, dass es ein Formular zum Öffnen von Dateien verwenden soll:
open(F, "<:utf8", "data");
oder Sie können verwenden, perl -CSD
was eine Abkürzung ist fürperl -CIOEio
S 7 I + O + E
D 24 i + o
Dann bekommst du
→ perl -CSD -pe 's/.*(..)$/$1/' data
ρε
小红
Wenn die PERLIO
Umgebungsvariable festgelegt ist und enthält, :utf8
wird dieses Verhalten ebenfalls aktiviert.
Es sieht so aus, als ob das Standardverhalten perl
auch zur Konfigurations-/Kompilierungszeit nicht veränderbar ist (cuonglm-Kommentar unten). Arch kann das jedenfalls nichtetwas einstellen.Ich bezweifle, dass Debian-Perl-Pakete das Standardverhalten ändern würden.
Antwort2
Das ist kein Systemproblem, sondern ein Problem des Systems perl
selbst.
-CIO
Stellen Sie nur die UTF-8-Kodierung auf STDIN
und ein STDOUT
, zwei der drei perl
vordefinierten Dateihandles (die Sie auch -E
für haben).STDERR
Bei Verwendung von:
perl -CIO -pe 's/.*(..)$/$1/' file
perl
Verwenden Sie den Diamant-Operator <>
zur Dateiverarbeitung. Seit wann wird der Diamant-Operator <>
verwendet ?offen (mit zwei Argumenten)STDIN
um über die Befehlszeile für jede Datei einen neuen Dateihandle zu erstellen. Diese Dateihandles werden von der von Ihnen auf und festgelegten UTF-8-Kodierung nicht beeinflusst STDOUT
.
Sie können also den Inhalt der Datei perl
über deren Standardeingabe übergeben und es wird funktionieren:
perl -CIO -pe 's/.*(..)$/$1/' <file
Weitere Optionen finden Sie unter@Matts Antwort.
Falls Sie perl
Ihr Gebietsschema als Standardcodierungsebene verwenden möchten, können Sie Folgendes verwenden:
perl -Mopen=:locale -pe 's/.*(..)$/$1/' file
Wenn Sie PERLIO
zum Einstellen der Kodierungsebene verwenden, sollten Sieverwenden :encoding(uf8)
statt:utf8
.
Durch die Verwendung :utf8
wird der Kodierungsschritt übersprungen. Dies kann beim Lesen ungültiger UTF-8-Bytefolgen zu Problemen führen und Sicherheitsprobleme verursachen.