我想替换未包含在<中的所有出现的字符串。 ...>

时间:2013-03-18 08:04:26

标签: php regex preg-replace

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

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

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:我在Replacing all occurences of a specific word which are not enclosed with the words OPEN and CLOSE?中看到了一些类似的东西,但无法弄清楚如何使其符合我的要求。

2 个答案:

答案 0 :(得分:2)

答案 1 :(得分:0)

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

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

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;
}

感谢大家。