1

我想通过在发送输出之前处理输出来对搜索的单词进行服务器端突出显示。

“服务器端”背后的原因是:

1) Unicode 文本的 Javascript 突出显示很糟糕。2) \b 不能使用 unicode(至少在 JS、AFAIK 中)。3) JS 中没有后向支持。

我正在使用下面的函数,但昨晚意识到为跳过 <...> 而编写的第一部分不起作用。

public function ss_highlight($terms, $buf)
{
    if (empty($terms))  {
        return $buf;;
    }

    /* sort before using length for better match */
    usort($terms, function($a, $b) {
        return mb_strlen($b) - mb_strlen($a);
    });
    $str_terms = implode('|', $terms);

    /* server side highlighter */
    $buf = preg_replace('/(<[^>]+>)*(?<=[\s|:|\-|>|\(|\)|\.|,|\/|^])('.$str_terms.')(?=[\s|:|\-|<|\(|\)|\.|,|\/]|$)/i', '$1<span class="highlight">$2</span>', $buf);

    return $buf;
}

任何想法,将不胜感激。

问候。

PS:我在替换所有出现的未包含在 OPEN 和 CLOSE 中的特定单词中看到了一些类似的东西?但无法弄清楚如何满足我的要求。

4

2 回答 2

2

不要尝试使用正则表达式解析 HTML!使用 HTML 解析器!

请参阅使用正则表达式 和正则表达式匹配开放标签(XHTML 自包含标签除外)在 PHP 中突出显示搜索词而不破坏锚标签

于 2013-03-18T08:08:20.320 回答
0

实际上,每个人都知道对 HTML 使用正则表达式是个坏主意,但是在这种情况下,我们真的不需要 DOM,因为我们只想替换一些出现在任何 < ... > 之外的文本。

这个解决方案对我来说似乎很好用:

public function ss_highlight($terms, $buf)
{
    if (empty($terms))  {
        return $buf;;
    }

    /* sort before using length for better match */
    usort($terms, function($a, $b) {
        return mb_strlen($b) - mb_strlen($a);
    });
    $str_terms = implode('|', $terms);

    /* server side highlighter */
    $buf = preg_replace_callback('#((?:(?!<[/a-z]).)*)([^>]*>|$)#si',
                        function ($matches) use ($str_terms) {
                            //return preg_replace('/(?<=[\s:\-\>\(\)\.,\/^])('.$str_terms.')(?=[\s:\-\<\(\)\.,\/]|$)/i', '<span class="highlight">$1</span>', $matches[1]).$matches[2];
                            return preg_replace('/(?<!\pL)('.$str_terms.')(?!\pL)/i', '<span class="highlight">$1</span>', $matches[1]).$matches[2];
                        }, $buf);

    return $buf;
}

谢谢大家。

于 2013-03-18T17:14:40.433 回答