2011-05-20 45 views
5

當我這樣做:Perl的正則表達式預編譯 - UTF8

use strict; use warnings; 
my $regex = qr/[[:upper:]]/; 
my $line = MyModule::get_my_line_from_external_source(); #file, db, etc... 
print "upper here\n" if($line =~ $regex); 

怎樣使用Perl會知道什麼時候它只能ascii uppercaseutf8 uppercase匹配嗎? 這是一個預編譯的正則表達式 - 所以有些Perl必須知道,什麼是大寫。取決於區域設置?如果是,如何將「C」語言環境中的utf8大寫與預編譯的正則表達式匹配?

更新基於tchrist的評論:

use strict; use warnings; use Encode; 
my $regex = qr/[[:upper:]]/; 

my $line = XXX::line(); 
print "$line: upper1 ", ($line =~ $regex) ? "YES" : "NO", "\n"; 

my $uline = Encode::decode_utf8($line); 
print "$uline: upper2 ", ($uline =~ $regex) ? "YES" : "NO", "\n"; 

package XXX; 
sub line { return "alpha-Ω"; } #returning octets - not utf8 chars 

輸出是:

alpha-Ω: upper1 NO 
alpha-Ω: upper2 YES 

是什麼意思,是預編譯的正則表達式是不是「硬預編譯」,而是「軟預編譯」 - 所以perl根據匹配的$行的utf8標誌替換'[[:upper:]]'。

+0

如果您在源代碼中使用文字UTF-8,那麼您只需要在作用域中使用「utf8」。 Perl會爲你解碼。 – tchrist 2011-05-20 14:09:46

回答

6

在Perl 5.14之前,這個沒有很好的定義。

隨着5.14,知道這是如何被編譯的模式,你有/u/l/d/a,或/aa圖案修飾。你也可以說

use re "/u"; 

use re "/msu"; 

把所有的這些標誌上的詞彙範圍。

例如,在5.14:

% perl -le 'print qr/foo/' 
(?^:foo) 
% perl -E 'say qr/foo/' 
(?^u:foo) 
% perl -E 'say qr/foo/l' 
(?^l:foo) 

我STEAR明確的語言環境;只使用全Unicode。

順便說一句,我會確保這個「外部源」給你一個正確解碼的字符串;也就是說,它的UTF8標誌打開了。字符函數在編碼字符串上效果不佳,因爲它們確實需要解碼字符串。

+1

那麼,在perl <5.14中匹配utf8 [:upper:]的正確方法是什麼?例如:「my $ regsrc = Encode :: decode_utf8('[[:upper:]]');我的$ regex = qr/$ regsrc /;#或者怎麼樣?或者在開始時足夠放入」use utf8;「? – kobame 2011-05-20 12:52:48

+0

'使用utf8'不足以在U + 80-U + FF上爲自己的源代碼獲取Unicode字符串語義,您應該可以說'utf :: upgrade($ string)'。已經被解碼了,否則就是UTF-8的正確編碼,如果是這樣的話,就表示它已經解碼了,然後任何正則表達式都可以正常工作,你可以使用'utf8 :: is_utf8($ string)'來測試它的UTF8標誌已經打開,Unicode屬性'\ p {upper}'將假定Unicode語義,但是這又要求字節字符串已經被轉換爲字符串了,我永遠不會使用'[[:upper:]]'' , – tchrist 2011-05-20 13:05:49

+0

優先考慮[Unicode :: Semantics](http://p3rl.org/Unicode::Semantics)而不是裸體'upgrade' API調用,不需要執行'is_utf8'測試 – daxim 2011-05-20 13:14:03