【问题标题】:Highlight text, except html tags突出显示文本,除了 html 标签
【发布时间】:2011-02-05 04:05:42
【问题描述】:

我正在使用下面的代码来突出显示文本中的一些关键字:

$message = str_ireplace($words,'<span class="hightlighted_text">'.$words.'</span>',$message);

文本可能包含一些html标签,例如&lt;img&gt;&lt;strong&gt;等。

如何突出显示“普通”文本,除了 html 标签之间的文本?因为当用户搜索“img”时,&lt;img&gt; 文本将被突出显示并且图像不再起作用。

【问题讨论】:

标签: php regex preg-replace


【解决方案1】:

使用某种 DOM 解析器。这不是你想用正则表达式做的事情。

【讨论】:

    【解决方案2】:

    来自http://forum.phpfrance.com/vos-contributions/remplacement-selectif-hors-dans-balises-html-t199.html

    function mon_rplc_callback($capture){
      global $arg;
      return ($arg['flag'] == 1)
      ? $arg['fct']($arg['from'], $arg['to'], $capture[1]).$capture[2]
      : $capture[1].$arg['fct']($arg['from'], $arg['to'], $capture[2]);
    }
    
    function split_tag($from, $to, $txt, $fct, $flag = 1){
      global $arg;
      $arg = compact('from', 'to', 'fct', 'flag');
      return preg_replace_callback('#((?:(?!<[/a-z]).)*)([^>]*>|$)#si', "mon_rplc_callback", $txt);
    }
    

    当 $flag == 1 时,替换函数在 HTML 之外应用。 当 $flag == -1 时,在 HTML 中应用替换函数。

    应用于您的示例,它会给出如下内容:

    echo split_tag($words, '<span class="hightlighted_text">'.$words.'</span>', $message, 'str_ireplace', 1);
    

    享受吧! ;)

    【讨论】:

    • 谢谢,但这没有 html 解析器。上面的海报说在这种情况下html解析器会更好(??)
    • 我告诉你正则表达式可以做得很好。另外,您不需要有效的 html 代码:它就可以工作。
    • 感谢您的回复。唯一的问题是当 de 关键字(必须突出显示)包含所有字母数字字符时,我会收到内存泄漏错误。
    • 哼。这看起来很奇怪。你能提供你使用的代码吗?顺便说一句,我刚刚阅读了关于为什么正则表达式无法解析 HTML 的论点。我完全同意整个事情,但这里的问题要简单得多:我们只需要知道我们是否在某个 HTML 标记内。我们不必解析 HTML 结构并解释树和不匹配的标签或其他一些错误。我们只知道 HTML 标签介于 之间。我相信正则表达式在这里非常适合。
    【解决方案3】:

    基于@Savageman 回复的更好的代码

    $str = '<a href="ba">ba</a>';
    $highlightWhat = "ba";
    $str = preg_replace_callback('#((?:(?!<[/a-z]).)*)([^>]*>|$)#si', function($m) use ($highlightWhat) {
                return preg_replace('~('.$highlightWhat.')~i', '<span style="background:#fff330">$1</span>', $m[1]) . $m[2];
            },
            $str);
    

    【讨论】: