Улучшите это регулярное выражение, чтобы preg_replace не бросал PREG_BACKTRACK_LIMIT_ERROR - PullRequest
0 голосов
/ 01 марта 2019

Я хочу удалить все теги scipt с HTML-страницы, кроме тех, которые содержат слово foo или bar.Итак, я пришел с этим утверждением:

$content = preg_replace('#<script((?!foo|bar).)*?</script>#is', '', $content);
echo "Last error: " + preg_last_error();

Это работает на небольших страницах.Но теперь у меня есть страница с 30 большими тегами сценария, и она не работает.Я получаю ошибку: PREG_BACKTRACK_LIMIT_ERROR

Поэтому я думаю, что мне нужно улучшить свое регулярное выражение, чтобы предотвратить эту ошибку, потому что это утверждение работает:

$content = preg_replace('#<script.*?</script>#is', '', $content); 

Но это утверждениеудаляет все теги скрипта, хотя я хочу сохранить некоторые из них.

Есть решение об увеличении pcre.backtrack_limit, но я не хочу идти по этому пути.Имхо должно быть лучшее решение.

Дело в том, что я не знаю, как это исправить, потому что проблема с регулярным выражением, насколько я вижу.

Не могли бы выпомогите мне сделать регулярное выражение лучше, чтобы эта ошибка не возникала?

1 Ответ

0 голосов
/ 01 марта 2019

Я бы настоятельно рекомендовал не , используя здесь регулярные выражения, а вместо этого использовать DOM-разбор , что часто более уместно в этом сценарии:

$doc = new \DOMDocument();
$doc->loadHTML($html, LIBXML_HTML_NODEFDTD);

$xpath = new \DOMXPath($doc);
foreach ($xpath->query('//script[contains(text(), \'foo\') or contains(text(), \'bar\')]') as $script_tag) {
  $script_tag->parentNode->removeChild($script_tag);
}

echo $doc->saveHTML();

Если у вас есть больше слов, вы можете вместо этого построить свой запрос xpath из массива:

$blacklist = ['foo', 'bar', 'apple', 'cold'];

$query = '//script[' . join(' or ', array_map(function($banword) { 
  return "contains(text(), '$banword')"; 
}, $blacklist)) . ']';

foreach ($xpath->query($query) as $script_tag) {
  $script_tag->parentNode->removeChild($script_tag);
}

Демо: https://3v4l.org/dHGDt

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...