求支持大小写与重音不敏感的PHP字符串单词高亮函数
PHP 不区分大小写和重音的字符串高亮函数
要实现不区分大小写、忽略重音且保留原字符串格式的高亮功能,核心思路是通过正则匹配时统一归一化(去除重音、转小写),但替换时保留原字符串的原始字符。以下是具体实现:
实现代码(依赖intl扩展,推荐)
function highlight($string, $term_to_search) { // 转义搜索词中的正则特殊字符,避免匹配错误 $escaped_term = preg_quote($term_to_search, '/'); // 创建转写器:将任意字符转为拉丁字符→去除重音→转小写,用于统一匹配规则 $transliterator = \Transliterator::create('Any-Latin; Latin-ASCII; Lower()'); $normalized_term = $transliterator->transliterate($term_to_search); // 构建正则模式:不区分大小写,匹配归一化后与搜索词一致的内容 $pattern = '/(' . preg_quote($normalized_term, '/') . ')/iu'; // 回调替换:保留原字符串的匹配内容,仅添加高亮标签 return preg_replace_callback($pattern, function($matches) use ($transliterator, $normalized_term) { // 对匹配到的原始字符做归一化,确认是否完全匹配(避免误判) $normalized_match = $transliterator->transliterate($matches[0]); if (strtolower($normalized_match) === $normalized_term) { return '<b>' . htmlspecialchars($matches[0], ENT_QUOTES) . '</b>'; } return $matches[0]; }, $string); } // 测试示例 echo highlight("my Striñg", "string"); // 输出:my <b>Striñg</b>
无intl扩展的替代方案
如果服务器未开启intl扩展,可以用iconv实现重音去除:
function removeAccents($str) { return iconv('UTF-8', 'ASCII//TRANSLIT//IGNORE', $str); } function highlight($string, $term_to_search) { $escaped_term = preg_quote($term_to_search, '/'); $normalized_term = strtolower(removeAccents($term_to_search)); $pattern = '/(' . preg_quote($normalized_term, '/') . ')/iu'; return preg_replace_callback($pattern, function($matches) use ($normalized_term) { $normalized_match = strtolower(removeAccents($matches[0])); if ($normalized_match === $normalized_term) { return '<b>' . htmlspecialchars($matches[0], ENT_QUOTES) . '</b>'; } return $matches[0]; }, $string); }
关键说明
- 避免原字符丢失:使用
preg_replace_callback而非直接str_replace,确保匹配到的原始字符(如Striñg)被保留,仅添加<b>标签。 - 归一化匹配:通过转写/去除重音、转小写,让
string能匹配Striñg、STRING、strïng等变体。 - 安全处理:添加
htmlspecialchars防止原字符串中的特殊HTML字符被解析,避免XSS风险(如果输出到HTML页面的话)。
内容的提问来源于stack exchange,提问作者Samir
相关产品推荐
相关产品推荐

