在我新安裝的 Arch 上,perl
Unicode 似乎不太好用。例如,給定以下輸入檔:
ελα ρε
王小红
這個命令應該給我每行的最後兩個字元:
$ 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
您描述的問題是我測試的系統上的標準行為。I
並O
影響標準輸入和標準輸出,所以這應該有效:
→ cat data | perl -CIO -pe 's/.*(..)$/$1/'
ρε
小红
然而這可能不會:
→ perl -CIO -pe 's/.*(..)$/$1/' data
ε
º¢
有還有兩個選項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
which 的簡寫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
本身的問題。
-CIO
STDIN
僅在和上設定 UTF-8 編碼STDOUT
,這是三個perl
預定義檔案句柄中的兩個(您也有-E
for )。STDERR
當您使用:
perl -CIO -pe 's/.*(..)$/$1/' file
perl
使用菱形運算子<>
處理檔案。從什麼時候<>
開始使用鑽石算子open(有兩個參數形式)要從命令行為每個檔案建立新的檔案句柄,這些檔案句柄不會受到您在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 位元組序列時可能會導致問題並導致安全性問題。