【问题标题】:Regex closing tag replacement issue正则表达式结束标签替换问题
【发布时间】:2011-07-08 08:34:50
【问题描述】:

如果关键字本身不在某个结束标记内,我们有一段正则表达式会在关键字周围添加一个<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>

它无法识别结束时的&lt;/a&gt;&lt;/em&gt;,所以它以...的形式出现。

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

我们不希望它这样做。任何人都可以看看是否有解决这个问题(是的,我知道不要使用正则表达式规则解析 HTML,所以发布指向那个臭名昭著的帖子的链接不是答案;-))

【问题讨论】:

  • 对不起,但是...如果您知道这一点,为什么您仍然使用正则表达式解析 HTML? ;-)
  • 我知道您知道不要使用正则表达式规则解析 HTML,所以我还是会将链接发布到臭名昭著的帖子:stackoverflow.com/questions/1732348/…

标签: php regex html-parsing


【解决方案1】:

以下正则表达式尝试匹配关键字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

警告

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

【讨论】:

  • $str = preg_replace('/(?&lt;!&lt;(a|b|i|u|em|strong).*?&gt;.*?)\btest\b(?!.*?&lt;/\1&gt;)/i', "&lt;strong&gt;\\2&lt;/strong&gt;", "A test line", 1); 给出错误:未知修饰符'\'
  • 我已经根据php正则表达式的限制更改了正则表达式。
  • 我必须承认正则表达式不太适合这种情况。不管怎样,这样的挑战总是很有趣。
  • 确实......现在的问题是你没有看到匹配词之前的文字......$str = preg_replace("/^.*?(?!&lt;(a|b|i|u|em|strong).*?&gt;.*?)\b(test)\b(?!.*?&lt;\/\1&gt;)/is", "&lt;strong&gt;\\2&lt;/strong&gt;", "A test line", 1);
  • 试试这个:$str = preg_replace("/^(.*?)(?!&lt;(a|b|i|u|em|strong).*?&gt;.*?)\b(test)\b(?!.*?&lt;\/\2&gt;)/is", "\\1&lt;strong&gt;\\3&lt;/strong&gt;", "A test line", 1);
猜你喜欢
  • 1970-01-01
  • 2012-04-27
  • 1970-01-01
  • 1970-01-01
  • 2011-09-07
  • 1970-01-01
  • 2012-07-06
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多