2011-07-10 192 views
1

我想知道PCRE如何檢測來自任何語言的字符。 我是測試此字符串:Unicode字符集中的「字」字符

"間違つ" 

PHP文件被編碼爲UTF-8和被適當地標記有字符集= UTF-8在內容類型代碼。

<?php 

$string="\xE9\x96\x93\xE9\x81\x95\xE3\x81\xA4"; //Bytestream from "間違つ" 
$string=preg_replace('/\w/','\w',$string); 
echo $string; 
echo "<br>"; 


$byte="\xE9"; //I've tried with each byte separately to find word characters 
if(preg_match('/\w/',$byte)){ 
    echo "$byte is a word"; 
    } 
else{ 
    echo "$byte is not a word"; 
    } 
?> 

"\xE9" "\xE9" "\xE3"來自所有的字節,都是單詞。

它顯示:

Displayed

我知道爲什麼符號出現。 解碼器使用Unicode替換字符,代碼點FFFD, 作爲解碼無效的UTF-8序列,而不是停止處理文本。 由於一個「單詞字符」被替換'\w' 代替,然後它打破了「字節安全性」顯示,因此存在無效序列。

所以問題是:

爲什麼,如果他們不合法的UTF-8序列這些字符類的字眼是否匹配?

如何知道這些字符實際上是所有Unicode字符集的單詞字符?

回答

2

您必須設置u-Flag,否則它將被解釋爲ISO-8859-1字符串。

下面的腳本示出了字符\w匹配而不u -flag:如果u -flag設置

header("Content-Type: text/plain"); 
$i = 255; 
while($i--) 
{ 
    preg_match('/\w/S', chr($i), $m); 
    printf("%' 1s \x%s\n", $m[ 0 ], strtoupper(bin2hex($m[ 0 ]))); 
} 

只有[A-ZA-Z]由\w匹配:

// added 'A' at the beginning and 'B' at the end 
preg_match_all('/\w/u', "A\xE9\x96\x93\xE9\x81\x95\xE3\x81\xA4B", $m); 
print_r($m); 

注意:如果u -Flag存在,preg_ *會靜默地解析字符串,如果它包含非Unicode字符(例如\ x80- \ xFF)。

2

我相信你的正則表達式引擎正在解釋你的字節流,就好像它們在ISO Latin-1(它們不是)編碼一樣。在ISO Latin-1的,

  • E3是與TILDE拉丁小寫字母A
  • E9是拉丁小字母E急性

這是 「字」 字,但

它們不是單詞字符。

您可以在正則表達式上設置/u修飾符,以請求它使用UTF-8而不是拉丁-1。請參閱PHP manual on pattern modifiers