2011-07-10 69 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