私の Perl はなぜ Unicode とうまく連携しないのでしょうか?

私の Perl はなぜ Unicode とうまく連携しないのでしょうか?

私の新しい Arch インストールでは、perlUnicode がうまく動作しないようです。たとえば、次の入力ファイルがあるとします。

ελα ρε
王小红

このコマンドを実行すると、各行の最後の 2 文字が返されます。

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

しかし、上記のように意味不明な結果になります。正しい出力は次のとおりです。

ρε
小红

gnome-terminator以下の両方とも期待どおりに動作するため、私のターミナル ( ) は UTF-8 をサポートしていることがわかります。

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

残念ながら、 がなければ-CIOperlファイルも正しく処理されません。

$ 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この動作も有効になります。

のデフォルトの動作は、perlconfigure/compile時に変更できないようです(以下のcuonglmコメント)。Archは確かにそうではありません。何も設定しません。Debian Perl パッケージがデフォルトの動作を変更するとは思えません。

答え2

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

-CIO3 つの定義済みファイルハンドルのうち 2 つでSTDINある と のみに UTF-8 エンコーディングを設定します( にも設定されています) 。STDOUTperl-ESTDERR

使用する場合:

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 バイト シーケンスを読み取るときに問題が発生し、セキュリティ上の問題が発生する可能性があります。

関連情報