PHP preg_replace:以大写/不区分变音的方式突出显示与关键字匹配的整个单词

时间:2018-08-20 13:29:36

标签: php regex preg-replace

我需要在UTF-8 $文本中突出显示与$ key匹配的单个单词或短语(整个单词,而不是子字符串)。这种匹配必须不区分大小写和变音符号。突出显示的文本必须保持原样(包括大写/小写字符和变音符号,如果存在)。

以下表达式达到了目标的一半:

$text = preg_replace( "/\b($key)\b/i", '<div class="highlight">$1</div>', $text );

不区分大小写,并且匹配整个单词,但是如果匹配$ key的$ text部分包含$ key中不存在的变音标记,则不会突出显示这些文本。 例如。我想在$ text中通过$ key =“ bjorn kallstrom”突出显示“BjörnKällström”。

欢迎任何绝妙的主意(使用preg_replace或其他PHP函数)。

2 个答案:

答案 0 :(得分:1)

一个想法是将键转换为用字符类替换所有有问题字符的模式:

$corr = ['a' => '[aàáâãäå]', 'o' => '[oòóôõö]',/* etc. */];

$key = 'bjorn kallstrom';

$pattern = '/\b' . strtr($key, $corr) . '\b/iu';

$text = preg_replace($pattern, '<em class="highlight">$0</em>', $text);

请注意,由于您要处理Unicode字符,因此需要使用u修饰符来避免意外行为,尤其是在单词边界方面。

如果您的按键已经包含重音符号,请先将其转换为ascii:

$key = 'björn kallstrom';
$key = iconv('UTF-8', 'ASCII//TRANSLIT', $key);

(如果您获得?代替字母,则意味着您的语言环境设置为C或POSIX。在这种情况下,请将其更改为en_US.UTF-8,或者将其更改为系统。请参见setlocale

还要看看非常有用的intl类:NormalizerTransliterator

注意:如果要突出显示多个键,请一次完成所有操作。按长度对数组进行排序(使用mb_strlen的数组中最长的数组),使用array_map音译ascii键,并用|插入数组。目标是获得模式:'/\b(?:' . implode('|', $keys) . ')\b/iu'bj[oòóôõö]rn k[aàáâãäå]llstr[oòóôõö]m单独出现在bj[oòóôõö]rn之前(例如)。

答案 1 :(得分:0)

仅通过函数调用是不可能的,您将必须实现它。

  1. 从HTML($document->documentElement->textContent)中提取文本
  2. 将文本拆分为单词并对其进行规范化-保留原始文字($words[$normalized][] = $original)-基本上,这为您提供了每个规范化单词的变体列表。
  3. 拆分并规范化搜索查询
  4. 从搜索查询中编译RegEx模式以匹配((word1_v1|word1_v2)\s*(word2_v1|word2_v2))u并验证(^(word1_v1|word1_v2)\s*(word2_v1|word2_v2)$)u
  5. 遍历HTML文档$xpath->evaluate('//text()')中的文本节点
  6. 使用preg_split()通过搜索字符串分隔文本,捕获定界符(搜索匹配项)
  7. 遍历该列表,如果不是搜索字符串匹配项,则将它们添加为文本节点,否则添加突出显示的HTML结构
  8. 删除原始文本节点。