2011-11-25 117 views
6

工作,我無法擺脫的特殊字符的¤而在字符串正則表達式不特定的特殊字符在Perl

$word = 'cɞi¤r$c❤u¨s'; 
$word =~ s/[^a-zöäåA-ZÖÄÅ]//g; 
printf "$word\n"; 

在第二行中我嘗試刪除任何非字母字符字符串$word。我希望得到詞馬戲團打印出來,而是我得到:

ci�rc�us 

OAA和表達OAA是,我需要包括在瑞典字母只是普通的字符。

+0

你正在使用哪個perl版本? Unicode支持逐漸被添加和完善。嘗試至少5.12,並看看choroba的答案。 'perl -v'來打印出版本。 [perl unicode手冊](http://perldoc.perl.org/perlunicode.html) – cfi

+0

版本v5.12.4 – Pithikos

+0

爲什麼有經驗的程序員不斷改變問題?現在,我的(低)經驗的用戶永遠不會找到他的問題的答案。 – Pithikos

回答

11

如果字符在你的源代碼中,一定要use utf8。如果他們正在從一個文件中讀取,binmode $FILEHANDLE, ':utf8'

請務必閱讀perldoc perlunicode

+0

我認爲編碼是正確的,因爲我可以'printf'cɞi¤r$c❤u¨söäå';'沒有問題。當我運行正則表達式時,問題就出現了。從正則表達式中刪除**öäå可以解決問題,但是我不能在字符串中使用這些字符:/ – Pithikos

+1

即使不使用utf8也可以打印字符串,但在這種情況下,Perl會打印_bytes_ ,而不是_characters_。這也是爲什麼它不能識別正則表達式中的字符。你讀過'perlunicode'嗎? – choroba

-7

正如pointed out by choroba,在Perl腳本的開頭添加這解決了它:

use utf8; 
binmode(STDOUT, ":utf8"); 

其中use utf8讓您在正則表達式正確使用特殊字符和binmode(STDOUT, ":utf8")讓你輸出的特殊字符正確的貝殼。

+3

這就是choroba已經提出的建議。你爲什麼提供他的答案副本?相反,用「答案」獎勵科羅巴(並且讚揚他)(然後刪除自己的答案) – cfi

+0

因爲我的回答更實用。我不想與他競爭。我試圖詳細說明未來的用戶在相同的問題上獲得堆棧。我認爲越多答案越好。 – Pithikos

+2

@Pithikos,你可以添加它作爲他的答案的一個次要評論,特別是如果它顯示你的方式。 – Qtax

3

簡短回答:添加使用utf8;以確保您的源代碼中的文字字符串被替換爲utf8,其中包含測試字符串的內容和正則表達式的內容。

龍答:

#!/usr/bin/env perl 

use warnings; 
use Encode; 

my $word = 'cɞi¤r$c❤u¨s'; 

foreach my $char (split //, $word) { 
    print ord($char) . Encode::encode_utf8(":$char "); 
} 

my $allowed_chars = 'a-zöäåA-ZÖÄÅ'; 

print "\n"; 

foreach my $char (split //, $allowed_chars) { 
    print ord($char) . Encode::encode_utf8(":$char "); 
} 

print "\n"; 

$word =~ s/[^$allowed_chars]//g; 

printf Encode::encode_utf8("$word\n"); 

執行它而不UTF8:

$ perl utf8_regexp.pl 
99:c 201:É 158: 105:i 194:Â 164:¤ 114:r 36:$ 99:c 226:â 157: 164:¤ 117:u 194:Â 168:¨ 115:s 
97:a 45:- 122:z 195:Ã 182:¶ 195:Ã 164:¤ 195:Ã 165:¥ 65:A 45:- 90:Z 195:Ã 150: 195:Ã 132: 195:Ã 133: 
ci¤rc¤us 

與UTF8執行它:

$ perl -Mutf8 utf8_regexp.pl 
99:c 606:ɞ 105:i 164:¤ 114:r 36:$ 99:c 10084:❤ 117:u 168:¨ 115:s 
97:a 45:- 122:z 246:ö 228:ä 229:å 65:A 45:- 90:Z 214:Ö 196:Ä 197:Å 
circus 

說明:

非ASCII字符你一個重新輸入到您的源代碼是由一個以上的字節表示。由於你的輸入是utf8編碼的。在純ASCII或拉丁-1終端中,字符將會是一個字節。

當不使用utf8模塊時,perl認爲您輸入的每個字節都是一個單獨的字符,就像您在分割和打印每個單獨的字符時可以看到的那樣。當使用utf8模塊時,它根據utf8編碼的規則將幾個字節的組合作爲一個字符正確對待。

正如您可以通過coincidence所看到的那樣,瑞典語字符的一些字節由與您的測試字符串中的某些字符組成的某些字節匹配而組成,並且它們將保留。即:utf8中的ö包含195:Ã164:¤ - 164最終成爲您允許的角色之一,並通過它。

解決的辦法是告訴perl你的字符串應該被認爲是utf-8。

encode_utf8調用是爲了避免有關寬字符被打印到終端的警告。與往常一樣,您需要解碼輸入,並根據輸入或輸出應處理/操作的字符編碼對輸出進行編碼。

希望這可以讓它更清晰。

+0

Blah,抱歉有重疊的答案。隨意刪除或downvote如果你想要; - / – nicomen