关于使用 /u 模式修饰符时 UTF-8 字符串的有效性,需要注意以下几点;
1. 如果模式本身包含无效的 UTF-8 字符,则会收到错误(如上述文档中所述 - “从 PHP 4.3.5 开始检查模式的 UTF-8 有效性”
2. 当主题字符串包含无效的 UTF-8 序列/代码点时,它基本上会导致 preg_* 函数“静默失败”,其中没有任何匹配,但没有指示字符串是无效的 UTF-8
3. PCRE 将五字节和六字节 UTF-8 字符序列视为有效(在模式和主题字符串中),但这些字符在 Unicode 中不受支持(参见“Linux 和 Unix HOWTO 的安全编程”的第 5.9 节“字符编码” - 可以在 http://www.tldp.org/ 和其他地方找到)
4. 有关在 PHP 中测试 UTF-8 字符串有效性(并丢弃五/六字节序列)的示例算法,请访问:http://hsivonen.iki.fi/php-utf8/
以下脚本应该可以让您了解哪些有效,哪些无效;
<?php
$examples = array(
'有效的ASCII' => "a",
'有效的2字节序列' => "\xc3\xb1",
'无效的2字节序列' => "\xc3\x28",
'无效的序列标识符' => "\xa0\xa1",
'有效的3字节序列' => "\xe2\x82\xa1",
'无效的3字节序列(在第2字节)' => "\xe2\x28\xa1",
'无效的3字节序列(在第3字节)' => "\xe2\x82\x28",
'有效的4字节序列' => "\xf0\x90\x8c\xbc",
'无效的4字节序列(在第2字节)' => "\xf0\x28\x8c\xbc",
'无效的4字节序列(在第3字节)' => "\xf0\x90\x28\xbc",
'无效的4字节序列(在第4字节)' => "\xf0\x28\x8c\x28",
'有效的5字节序列(但不是Unicode!)' => "\xf8\xa1\xa1\xa1\xa1",
'有效的6字节序列(但不是Unicode!)' => "\xfc\xa1\xa1\xa1\xa1\xa1",
);
echo "++模式中无效的UTF-8\n";
foreach ( $examples as $name => $str ) {
echo "$name\n";
preg_match("/".$str."/u",'Testing');
}
echo "++ preg_match() 示例\n";
foreach ( $examples as $name => $str ) {
preg_match("/\xf8\xa1\xa1\xa1\xa1/u", $str, $ar);
echo "$name: ";
if ( count($ar) == 0 ) {
echo "没有匹配到任何内容!\n";
} else {
echo "匹配到 {$ar[0]}\n";
}
}
echo "++ preg_match_all() 示例\n";
foreach ( $examples as $name => $str ) {
preg_match_all('/./u', $str, $ar);
echo "$name: ";
$num_utf8_chars = count($ar[0]);
if ( $num_utf8_chars == 0 ) {
echo "没有匹配到任何内容!\n";
} else {
echo "匹配到 $num_utf8_chars 个字符\n";
}
}
?>