這裏是一個簡單的替換,它在unicode字符串的大寫字符周圍添加括號。正如你所看到的,結果是相當醜陋:邏輯Unicode字符的Perl正則表達式替換
~$ echo "Whatéver 5" | perl -ape "s/(\p{Upper})/(\1)/g"
(W)hat(�)�ver 5
我的理解是,正則表達式的「代碼點」,而不是「合乎邏輯的人物」的動作,這樣會將我的「E」變成無意義的字符。有沒有辦法強制正則表達式一次處理邏輯unicode字符?
感謝,
這裏是一個簡單的替換,它在unicode字符串的大寫字符周圍添加括號。正如你所看到的,結果是相當醜陋:邏輯Unicode字符的Perl正則表達式替換
~$ echo "Whatéver 5" | perl -ape "s/(\p{Upper})/(\1)/g"
(W)hat(�)�ver 5
我的理解是,正則表達式的「代碼點」,而不是「合乎邏輯的人物」的動作,這樣會將我的「E」變成無意義的字符。有沒有辦法強制正則表達式一次處理邏輯unicode字符?
感謝,
假設你的終端使用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
「上部」 是 「大寫」 的同義詞,並且我們可以甲肝寫過 \ p {大寫}等同地\ p {上部}
和
例如,\ p {大寫}與 Unicode的 「大寫」 屬性
匹配任何單個字符
看起來好像如果您嘗試在字節字符串上使用\p{Upper}
,您將不會從Perl獲得任何警告。 0xC0
到0xDE
範圍內的字節也將匹配大寫屬性。嘗試
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)0xC3
和0xA9
和0xC3
將匹配的Unicode Upper
財產。因此
甲解決問題的方法是在標準輸入和輸出加UTF-8編碼的層(可以使用-CS
結合-CI
和-CO
):
echo "Whatéver 5" | perl -CS -ape "s/(\p{Upper})/(\1)/g"
與輸出:
(W)hatéver 5
你還沒告訴Perl來期待UTF-8的輸入,所以它處理的編碼的每個字節作爲一個單獨的字符
在你可以設置默認的編碼方案這樣
use open ':std' => ':encoding(UTF-8)'
在命令行上的三個標準IO通道,該選項-CS
做同樣的事情,所以這應該爲你工作。我已經刪除了不必要的自動分割選項,並與替換字符串
echo "Whatéver 5" | perl -CS -pe "s/(\p{Upper})/($1)/g"
正如其他答案所示,在Perl中打開UTF-8是一個零碎的過程。對於語法和原始字符串,有use utf8
。那麼你必須確保你所有的文件句柄都是UTF-8。那@ARGV
呢? readdir
? glob
? ``
的輸出?
沒有比用一半的程序工作在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
有些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) –