私のPerlがUnicodeをうまく処理できないのはなぜですか?

私のPerlがUnicodeをうまく処理できないのはなぜですか?

新しいArchインストールでは、perlUnicodeが正しく機能していないようです。たとえば、次の入力ファイルが提供されます。

ελα ρε
王小红

このコマンドは、各行の最後の2文字を提供する必要があります。

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

しかし、上に見られるように、私は横説説です。正しい出力は次のとおりです。

ρε
小红

gnome-terminator私の端末()はすべて期待どおりに機能するため、UTF-8をサポートしていることがわかります。

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

残念ながら、ファイルを正しく処理せず、-CIO処理しません。perl

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

ロケールの問題もあってはいけません。

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

Perlパッケージをインストールする必要があるようですが、どのパッケージなのかわかりません。関連情報:

$ 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

PerlのインストールをUnicodeと互換性を持たせるにはどうすればよいですか?

答え1

説明した問題は、私がテストしたシステムの標準動作です。 stdinとstdoutに影響を与えるIので、O次のように動作します。

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

ただし、以下の場合は該当しない場合があります。

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

持つ2つのオプションがありますperl -C好きな行動を作りましょう。

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

これは基本的にPerlのファイルオープン形式を使用していると言います。

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

perl -CSDまたは、次の略語を使用できます。perl -CIOEio

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

それからあなたは得る

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

PERLIO環境変数が設定されて含まれていても、この動作は有効になります:utf8

perl設定/コンパイル時にもデフォルトの動作を変更できないようです(下記cuonglmの説明)。アーチは確かにそうではありません何でも設定してください。私はDebian Perlパッケージがデフォルトの動作を修正すると思います。

答え2

これはシステムの問題ではなく、perlシステム自体の問題です。

-CIOSTDINSTDOUT3つの事前定義されたファイルハンドルのうち2つとのみUTF-8エンコーディングを設定しますperl(forにもあります-E)。STDERR

あなたが使用するとき:

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

perlファイルを処理するには、ダイヤモンド演算子を使用してください<>。いつから<>ダイヤモンドカウンターを使い始めましたか?open(2つのパラメータ型を持つ)コマンドラインから各ファイルの新しいファイルハンドルを作成するには、これらのファイルハンドルはおよびSTDINに設定したUTF-8エンコーディングの影響を受けませんSTDOUT

したがって、標準入力を介してファイルの内容を渡すとperl機能します。

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

その他のオプションについては、次を参照してください。@マットの答え


perlロケールをデフォルトのエンコードレイヤーとして使用するには、次のものを使用できます。

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

PERLIOエンコードレイヤーを設定するために使用するときは、次のようにする必要があります。:encoding(uf8)代わりに使用:utf8

エンコードスキップステップを使用すると、:utf8無効なUTF-8バイトシーケンスを読み取るときに問題が発生し、セキュリティの問題が発生する可能性があります。

関連情報