正则表达式关闭标签更换问题

时间:2011-07-08 08:34:51

标签: php regex html-parsing

我们有一段正则表达式,如果关键字不在某个结束标记内,则会在关键字周围添加<strong>标记。这一直很好用......

foreach ($keywords as $keyword) {
    $str = preg_replace("/(?!(?:[^<]+>|[^>]+(<\/strong>|<\/a>|<\/b>|<\/i>|<\/u>|<\/em>)))\b(" . preg_quote($keyword, "/") . ")\b/is", "<strong>\\2</strong>", $str, 1);
}

因此,如果关键字为test,则会发生变化:

A test line

为:

A <strong>test</strong> line

但这不会改变:

<a href="">A test line</a>

正如您所看到的,我们希望它忽略的结束标记列表位于正则表达式中。

我们遇到了一个字符串问题,如下所示:

<a href="">A test <em>line</em></a>

它没有意识到关闭</a></em>,所以它会以...的形式出现......

<a href="">A <strong>test</strong> <em>line</em></a>

我们不希望它这样做。任何人都可以看到是否有一个修复程序(是的,我知道不解析HTML与正则表达式规则,所以发布到该臭名昭着的帖子的链接不是答案; - ))

1 个答案:

答案 0 :(得分:2)

以下正则表达式尝试匹配test标记未包含的关键字a,b,i,u,em,strong

<强>正则表达式

/^.*?(?!<(a|b|i|u|em|strong).*?>.*?)\btest\b(?!.*?<\/\1>)/i

<强>测试

A test line                          => MATCH
<a href="">A test line</a>           => NO MATCH
<a href="">A test <em>line</em></a>  => NO MATCH

<强>讨论

^.*?(?!<(a|b|i|u|em|strong).*?>.*?)   => The keyword `test' must not be preceded by 
                                         any tag listed followed by any character
\btest\b                              => Here we define the keyword we want to match
(?!.*?</\1>)                          => The keyword `test' must not be followed by
                                         the tag opened previously

提示

您可以像这样增强多个关键字(在下面的示例中为kw1,kw2,kw3)的正则表达式:

/^.*?(?!<(a|b|i|u|em|strong).*?>.*?)\b(?:kw1|kw2|kw3)\b(?!.*?<\/\1>)/i

警告

这个正则表达式实际上适用于所提供的测试,但并非在所有情况下都适用。