Regex закрывающая проблема замены тега - PullRequest
1 голос
/ 08 июля 2011

У нас есть фрагмент регулярного выражения, который добавляет тег <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 Ответ

2 голосов
/ 08 июля 2011

Следующее регулярное выражение пытается найти ключевое слово test, не заключенное в теги a,b,i,u,em,strong.

Regex

/^.*?(?!<(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

Внимание

Это регулярное выражение на самом деле работает по предоставленному тесту, но не во всех случаях.

...