如果您的腳本和輸入文件使用相同的編碼進行編碼,則您的代碼將按原樣運行。
$ cat>test.html
ùmbrella ùnder ùùùùù ùtters
$ perl a.pl
$ cat out/test.html
umbrella under uuuuu utters
你的程序是越野車,雖然。假設我們正在談論UTF-8。Perl的實際看到
$str =~ s/\xC3\xB9/u/g;
雖然這並沒有那麼糟糕,想象一下,如果你有
$str =~ s/[ùú]/u/g;
的Perl會認爲這是
$str =~ s/[\xC3\xB9\xC3\xBA]/u/g;
這會變成ù
(C3 B9
)爲uu
和é
(C3 A9
)插入u<garbage>
。
對於Perl來識別程序中的任何非ASCII字符,您必須確保程序文件使用UTF-8進行編碼,並且您需要在文件頂部添加use utf8;
。隨着use utf8;
,Perl中看到
$str =~ s/[ùú]/u/g;
或者說
$str =~ s/[\xF9\xFA]/u/g; # F9 and FA are the Unicode Code Points for ù and ú
然而,增加use utf8;
只是解決方案的一半。我們改變了Perl看到正則表達式的方式,但我們沒有改變$str
,所以它們不可能再匹配。我們比較ù
(C3 B9
)與ù
(F9
)Unicode代碼點編碼
始終解碼你的投入。始終對輸出進行編碼。
我們已經解碼的一個輸入(程序本身)。現在我們需要對文件的內容做同樣的事情。
同樣,我們需要編碼輸出。這不僅包括文件的內容,還包括輸出到STDERR的警告。
大部分由
use open ':std', ':encoding(UTF-8)';
做它增加了一個編碼層STDIN,STDOUT和STDERR,並設置編譯的詞法範圍內打開文件的默認編碼層。
#!/usr/bin/perl
use utf8;
use open ':std', ':encoding(UTF-8)';
use strict;
use warnings;
my $in_qfn = 'test.html';
my $out_qfn = 'out/test.html';
# :encoding(UTF-8) is added by "use open".
open(my $in_fh, '<', $in_qfn) or die("Can't open \"$in_qfn\": $!\n");
open(my $out_fh, '>', $out_qfn) or die("Can't create \"$out_qfn\": $!\n");
while (<$in_fh>) {
s/[ùú]/u/g;
print($out_fh $_);
}
如果使用文件::嘟嘟地喝,你需要告訴它的文件進行解碼(或自己對其進行解碼),因爲它open
不在use open
的範圍。
#!/usr/bin/perl
use utf8;
use open ':std', ':encoding(UTF-8)';
use strict;
use warnings;
use File::Slurp qw(read_file write_file);
my $in_qfn = 'test.html';
my $out_qfn = 'out/test.html';
my $file = read_file($in_qfn, binmode => ':encoding(UTF-8)');
$file =~ s/[ùú]/u/g;
write_file($out_qfn, { binmode => ':encoding(UTF-8)' }, $file);
@siam的感謝!我不得不添加「使用utf8;」頂部還有 – Xavia
@siam:你在想Python!這只是Perl中的一個評論。 – Borodin
[檔案::嘟嘟地喝壞了,錯了。(http://blogs.perl.org/users/leon_timmermans/2015/08/fileslurp-is-broken-and-wrong.html) – ThisSuitIsBlackNot