2012-10-01 45 views
4

我試圖用單引號或雙引號替換各種字符。大型Unicode代碼點上的Perl正則表達式匹配

這裏是我的測試文件:

# Replace all with double quotes 
" fullwidth 
「 left 
」 right 
„ low 
" normal 

# Replace all with single quotes 
' normal 
‘ left 
’ right 
‚ low 
‛ reverse 
` backtick 

我試圖做到這一點...

perl -Mutf8 -pi -e "s/[\x{2018}\x{201A}\x{201B}\x{FF07}\x{2019}\x{60}]/'/ug" test.txt 
perl -Mutf8 -pi -e 's/[\x{FF02}\x{201C}\x{201D}\x{201E}]/"/ug' text.txt 

但只有反引號字符被正確更換。我認爲它與其他代碼點太大有關,但我無法找到任何文檔。

這裏我有一個one-liner轉儲的Unicode代碼點,以驗證它們符合我的正則表達式。

$ awk -F\ '{print $1}' test.txt | \ 
    perl -C7 -ne 'for(split(//)){print sprintf("U+%04X", ord)." ".$_."\n"}' 

U+FF02 " 
U+201C 「 
U+201D 」 
U+201E „ 
U+0022 " 

U+0027 ' 
U+2018 ‘ 
U+2019 ’ 
U+201A ‚ 
U+201B ‛ 
U+0060 ` 

爲什麼我的正則表達式不匹配?

回答

16

它不匹配,因爲您在致電Perl時忘記了-CSAD,並且沒有在您的環境中設置$PERL_UNICODE。你只說-Mutf8宣佈你的源代碼是在該編碼。這不會影響您的I/O。

您需要:

$ perl -CSAD -pi.orig -e "s/[\x{2018}\x{201A}\x{201B}\x{FF07}\x{2019}\x{60}]/'/g" test.txt 

我確實提到這樣的事情在this answer幾次。

+0

非常感謝。 –

+0

@tchrist,請通過將-CSAD替換爲-CSD來更正您的答案。我沒有編輯權力這樣做。 –

+0

@HansDeragon完成。 – tchrist

6

隨着use utf8;,你告訴Perl你的源代碼是UTF-8。這是無用的(雖然無害),因爲你已經限制你的源代碼到ASCII。

隨着/u,你告訴Perl來使用\s\d\w Unicode的定義。這是無用的(儘管無害),因爲你不使用任何這些模式。

您沒有對輸入進行解碼,所以您的輸入僅包含字節,因此您班級中的大多數字符(例如\x{2018})都不可能與任何內容匹配。你需要解碼你的輸入(當然,編碼你的輸出)。使用-CSD可能會這樣做。

perl -CSD -i -pe' 
    s/[\x{2018}\x{201A}\x{201B}\x{FF07}\x{2019}\x{60}]/\x27/g; 
    s/[\x{FF02}\x{201C}\x{201D}\x{201E}]/"/g; 
' text.txt 
+0

我討厭弄清楚如何在shell中引用東西。我通常只是選擇'\ x27'技巧。 – tchrist

+0

我只是做'''⇒''''''沒有想到,買呀,''''''\ x27'是個好主意。 – ikegami

+0

我認爲你的意思是「需要解碼你**輸入**」,並且可能還需要「編碼你的輸出」。 – tchrist