这不是一个完整的答案,因为我没有说为什么有些 PHP 函数”无效编码的字符串完全失败“而其他人则不然:请参阅问题评论中的@deceze 和@hakre 答案。
如果您正在寻找 PCRE 替代品str_word_count()
,看我的preg_word_count()
below.
PS:关于“PHP5的内置库行为统一” 讨论,我的结论是 PHP5 还不错,但是我们创建了很多用户定义的包装(外观)函数(参见 PHP 框架的多样性!)...或者等待 PHP6 :-)
谢谢@pebbl!如果我理解你的链接,PHP 缺少错误消息 http://php.net/manual/en/reference.pcre.pattern.modifiers.php#54805。因此,我所图示的问题的一个可能的解决方法是添加一个错误条件......我发现这里的条件 https://stackoverflow.com/a/1523574/287948(它确保有效的utf8!)...并且感谢@deceze记住存在一个内置函数来检查这个条件(我之后编辑了代码)。
将问题放在一起,将解决方案转换为函数(已编辑,感谢 @hakre 评论!),
function my_word_count($s,$triggError=true) {
if ( preg_match_all('/[-\'\p{L}]+/u',$s,$m) !== false )
return count($m[0]);
else {
if ($triggError) trigger_error(
// not need mb_check_encoding($s,'UTF-8'), see hakre's answer,
// so, I wrong, there are no 'misteious error' with preg functions
(preg_last_error()==PREG_BAD_UTF8_ERROR)?
'non-UTF8 input!': 'other error',
E_USER_NOTICE
);
return NULL;
}
}
现在(在思考@hakre答案后编辑),关于统一的行为:我们可以使用 PCRE 库开发一个合理的函数来模仿str_word_count
行为,接受错误的 UTF8。对于这个任务我使用了@bobinceiconv tip https://stackoverflow.com/a/1523574/287948:
/**
* Like str_word_count() but showing how preg can do the same.
* This function is most flexible but not faster than str_word_count.
* @param $wRgx the "word regular expression" as defined by user.
* @param $triggError changes behaviour causing error event.
* @param $OnBadUtfTryAgain mimic the str_word_count behaviour.
* @return 0 or positive integer as word-count, negative as PCRE error.
*/
function preg_word_count($s,$wRgx='/[-\'\p{L}]+/u', $triggError=true,
$OnBadUtfTryAgain=true) {
if ( preg_match_all($wRgx,$s,$m) !== false )
return count($m[0]);
else {
$lastError = preg_last_error();
$chkUtf8 = ($lastError==PREG_BAD_UTF8_ERROR);
if ($OnBadUtfTryAgain && $chkUtf8)
return preg_word_count(
iconv('CP1252','UTF-8',$s), $wRgx, $triggError, false
);
elseif ($triggError) trigger_error(
$chkUtf8? 'non-UTF8 input!': "error PCRE_code-$lastError",
E_USER_NOTICE
);
return -$lastError;
}
}
展示(尝试其他输入 https://stackoverflow.com/a/19274144!):
$s = "THE UTF-8 NO-BREAK\xA0SPACE"; // a non-ASCII byte
print "\n-- str_word_count=".str_word_count($s,0);
print "\n-- preg_word_count=".preg_word_count($s);
$s = "THE UTF-8 NO-BREAK\xC2\xA0SPACE"; // utf8-encoded nbsp
print "\n-- str_word_count=".str_word_count($s,0);
print "\n-- preg_word_count=".preg_word_count($s);