2008-10-15 125 views
8

我正在尋找一種方法來匹配Unicode字符串中只有完全組成的字符。如何在Perl中匹配Unicode字符串中完全組成的字符?

[:print:]依賴任何包含此字符類的正則表達式實現中的語言環境?例如,它是否與日文字符'あ'相匹配,因爲它不是控制字符,或者是[:print:]總是成爲ASCII碼0x20到0x7E?

是否有任何字符類,包括Perl RE,可以用來匹配控制字符以外的任何東西?如果[:print:]僅包含ASCII範圍內的字符,我會假設[:cntrl:]也是。

回答

6
echo あ| perl -nle 'BEGIN{binmode STDIN,":utf8"} print"[$_]"; print /[[:print:]]/ ? "YES" : "NO"' 

雖然它會產生一個關於寬字符的警告,但大多數情況下,但是它給了你一個想法:你必須確定你正在處理一個真正的Unicode字符串(檢查utf8 :: is_utf8)。或者根本檢查perlunicode - 整個主題仍然讓我頭暈目眩。

+1

通過在命令行中提供選項-CS,可以擺脫醜陋的BEGIN {binmode STDIN,「:utf8」} kludge。 – moritz 2008-10-15 06:43:30

2

是的,這些表達式是區域設置相關的。

+0

您能否命名允許[:print:]尊重日語UTF-8語言環境/編碼的環境和/或正則表達式實現?我使用日語UTF-8語言環境/編碼在Linux中使用Perl,並且它與日文字符不匹配。 – dreamlax 2008-10-15 03:14:58

1

您始終可以使用字符類[^[:cntrl:]]來匹配非控制字符。

+1

這不符合Unicode控制字符(在我的環境設置和使用Perl)。有用於改變文本方向等的Unicode控制字符。使用[^ [:ctrnl:]]將匹配這些Unicode字符串,但不匹配ASCII字符串。 – dreamlax 2008-10-15 04:03:56

5

我認爲你不想或不需要區域設置,但是,而是Unicode。如果你已經解碼了一個文本字符串,\w將匹配任何語言的單詞字符,\d匹配不僅僅是0..9,而是每個Unicode數字等。在正則表達式中,你可以用\p{PropertyName}查詢Unicode屬性。特別有趣的可能是\p{Print}Here's a list of all the available Unicode character properties

我寫了一個article about the basics and subtleties of Unicode and Perl,它應該給你一個好主意,讓perl將你的字符串識別爲一個字符序列,而不僅僅是一個字節序列。

更新:使用Unicode,您不會得到語言相關的行爲,而是無論語言如何,都會有默認值。這可能是也可能不是你想要的,但是爲了區分priintable/control character,我不明白你爲什麼需要語言依賴的行爲。

4

\X與完全組合的字符(序列)相匹配。證明:

#!/usr/bin/env perl 
use 5.010; 
use utf8; 
use Encode qw(encode_utf8); 

for my $string (qw(あ ご ご), "\x{3099}") { 
    say encode_utf8 sprintf "%s $string", $string =~ /\A \X \z/msx ? 'ok' : 'nok'; 
} 

測試數據爲:正常的字符,-組合前的字符,一個組合字符序列和一個結合字符(其中「不計數」自行,第3章的簡化Unicode)的。

\X替代[[:print:]]以查看Tanktalus的答案在最後兩種情況下產生錯誤匹配。