2016-09-02 80 views
0

這裏是一個簡單的替換,它在unicode字符串的大寫字符周圍添加括號。正如你所看到的,結果是相當醜陋:邏輯Unicode字符的Perl正則表達式替換

~$ echo "Whatéver 5" | perl -ape "s/(\p{Upper})/(\1)/g" 
(W)hat(�)�ver 5 

我的理解是,正則表達式的「代碼點」,而不是「合乎邏輯的人物」的動作,這樣會將我的「E」變成無意義的字符。有沒有辦法強制正則表達式一次處理邏輯unicode字符?

感謝,

+0

有些som在輸入和輸出上缺少UTF8 PerlIO層。以下工作如預期:'echo -n「Whatéver5」| perl -Mutf8 -CSDA -pe「s /(\ p {Upper})/(\ 1)/ g」'。另請參見[大寫Unicode的正則表達式不匹配「Ó」?](http://stackoverflow.com/questions/10891643/regex-for-uppercase-unicode-does-not-match-%C3%93) –

回答

1

假設你的終端使用UTF-8編碼的正確$1取代\1

$ echo -n "é" | perl -ne 'printf "%vX\n", $_' 

給出

C3.A9 

所以Perl程序的輸入沒有被內部轉換爲Unicode(它仍然是一個UTF-8字節的字符串)

要輸入轉換成一個Perl的字符串,使用選項-CI標準輸入流添加UTF-8層:

$ echo -n "é" | perl -CI -ne 'printf "%vX\n", $_' 

輸出是現在,如果你

E9 

然而也嘗試將字符打印回標準輸出 ,您將不會得到é,而是從終端獲得一個Unicode字符替換字符。這是因爲字符0xE9是Unicode,但終端預計UTF-8,而0xE9是無效的UTF-8:

$ echo -n "é" | perl -CI -nE 'printf "$_: %vX\n", $_, $_' 
�: E9 

要得到正確的輸出,你可以在標準添加UFT-8編碼層也(使用-CO標誌)輸出流:

$ echo -n "é" | perl -CIO -nE 'printf "$_: %vX\n", $_, $_' 
é: E9 

根據perlunicode

「上部」 是 「大寫」 的同義詞,並且我們可以甲肝寫過 \ p {大寫}等同地\ p {上部}

例如,\ p {大寫}與 Unicode的 「大寫」 屬性

匹配任何單個字符

看起來好像如果您嘗試在字節字符串上使用\p{Upper},您將不會從Perl獲得任何警告。 0xC00xDE範圍內的字節也將匹配大寫屬性。嘗試

perl -E 'for $i (0x80..0xFF) {$_=chr $i; printf "%x\n", $i if /\p{Upper}/}' 

這說明你得到的輸出:

$ echo "Whatéver 5" | perl -ape "s/(\p{Upper})/(\1)/g" 
(W)hat(�)�ver 5 

這裏,信é表示爲2個字節(UTF-8)0xC30xA90xC3將匹配的Unicode Upper財產。因此

甲解決問題的方法是在標準輸入和輸出加UTF-8編碼的層(可以使用-CS結合-CI-CO):

echo "Whatéver 5" | perl -CS -ape "s/(\p{Upper})/(\1)/g" 

與輸出:

(W)hatéver 5 
2

你還沒告訴Perl來期待UTF-8的輸入,所以它處理的編碼的每個字節作爲一個單獨的字符

在你可以設置默認的編碼方案這樣

use open ':std' => ':encoding(UTF-8)' 

在命令行上的三個標準IO通道,該選項-CS做同樣的事情,所以這應該爲你工作。我已經刪除了不必要的自動分割選項,並與替換字符串

echo "Whatéver 5" | perl -CS -pe "s/(\p{Upper})/($1)/g" 
2

正如其他答案所示,在Perl中打開UTF-8是一個零碎的過程。對於語法和原始字符串,有use utf8。那麼你必須確保你所有的文件句柄都是UTF-8。那@ARGV呢? readdirglob``的輸出?

沒有比用一半的程序工作在ASCII碼而另一半工作在UTF-8下更糟糕的了。 utf8::all來救援!

安裝它,添加use utf8::all,它會打開UTF-8 ...所有這一切。別人知道了,你不必擔心。

$ echo "Whatéver 5" | perl -ape "use utf8::all; s/(\p{Upper})/(\1)/g" 
(W)hatéver 5