Вопрос по regex, php – Разбор HTML-комментариев с помощью PHP, но без условных выражений

6

В настоящее время я использую PHP и регулярное выражение для удаления всех комментариев HTML со страницы. Сценарий работает хорошо ... слишком хорошо. Он удаляет все комментарии, включая мои условные комментарии в. Вот что я получил:

<code><?php
  function callback($buffer)
  {
        return preg_replace('/<!--(.|\s)*?-->/', '', $buffer);
  }

  ob_start("callback");
?>
... HTML source goes here ...
<?php ob_end_flush(); ?>
</code>

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

<code><!--[if !IE]><!-->
<link rel="stylesheet" href="/css/screen.css" type="text/css" media="screen" />
<!-- <![endif]-->

<!--[if IE 7]>
<link rel="stylesheet" href="/css/ie7.css" type="text/css" media="screen" />
<![endif]-->

<!--[if IE 6]>
<link rel="stylesheet" href="/css/ie6.css" type="text/css" media="screen" />
<![endif]-->
</code>

ура

Ваш Ответ

5   ответов
0

понравится ли движку PHP регулярное выражение, но попробуйте этот шаблон:

'/<!--(.|\s)*(\[if .*\]){0}(.|\s)*?-->/'
замена моего регулярного выражения этим предложит всплывающее окно сохранения загрузки страницы index.php, а не ее рендеринг. Ian
22

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

Вот моя попытка. Чтобы соответствовать только обычные комментарии, это будет работать. Это стало настоящим чудовищем, извините за это. Я проверил это достаточно широко, кажется, что это хорошо, но я не даю никаких гарантий.

<!--(?!\s*(?:\[if [^\]]+]|<!|>))(?:(?!-->).)*-->

Объяснение:

<!--                #01: "<!--"
(?!                 #02: look-ahead: a position not followed by:
  \s*               #03:   any number of space
  (?:               #04:   non-capturing group, any of:
    \[if [^\]]+]    #05:     "[if ...]"
    |<!             #06:     or "<!"
    |>              #07:     or ">"
  )                 #08:   end non-capturing group
)                   #09: end look-ahead
(?:                 #10: non-capturing group:
  (?!-->)           #11:   a position not followed by "-->"
  .                 #12:   eat the following char, it's part of the comment
)*                  #13: end non-capturing group, repeat
-->                 #14: "-->"

Шаги № 02 и № 11 имеют решающее значение. # 02 гарантирует, что следующие символы не обозначают условный комментарий. После этого # 11 гарантирует, что следующие символы не обозначают конец комментария, а # 12 и # 13 вызывают фактическое соответствие.

Подать заявку с & quot; глобальным & quot; и & quot; точка & quot; флаги.

Чтобы сделать обратное (сопоставлять только условные комментарии), это будет примерно так:

<!(--)?(?=\[)(?:(?!<!\[endif\]\1>).)*<!\[endif\]\1>

Объяснение:

<!                  #01: "<!"
(--)?               #02: two dashes, optional
(?=\[)              #03: a position followed by "["
(?:                 #04: non-capturing group:
  (?!               #05:   a position not followed by
    <!\[endif\]\1>  #06:     "<![endif]>" or "<![endif]-->" (depends on #02)
  )                 #07:   end of look-ahead
  .                 #08:   eat the following char, it's part of the comment
)*                  #09: end of non-capturing group, repeat
<!\[endif\]\1>      #10: "<![endif]>" or "<![endif]-->" (depends on #02)

Опять же, примените с & quot; глобальным & quot; и & quot; точка & quot; флаги.

Шаг # 02 из-за "выявленного на нижнем уровне" синтаксис, см .:& quot; MSDN - Об условных комментариях & quot;.

Я не совсем уверен, где пробелы разрешены или ожидаются. добавлять\s* к выражению, где это уместно.

Нет, это не так. Вы должны прочитать документы на preg_replace. :-)
У вас есть «шанс» читать документы прямо сейчас:php.net/manual/en/function.preg-replace.php :)) (также:php.net/manual/en/pcre.pattern.php )
Многое перепробовал с другими регулярными выражениями & apos; но этот был окончательным, и он работал, как я хотел.
Привет Томалак, спасибо за ваш вклад и подробные объяснения. Делает регулярные выражения намного проще :). Однако я только что попробовал ваше решение, и оно вообще не отображает ничего, кроме пустой страницы. Полная строка, которую я использую, такова: return preg_replace (& amp; & lt;! - (?! \ S * (?: [If [^]] +] | & lt;! | & Gt;)) (? :(? ! - & gt;).) * - & gt; '', '' ', $ buffer); Это правильно? Ian
Я должен признать, что раньше я не сталкивался с preg_replace, поэтому я, как только у меня появится шанс, прочитал документы. Однако, в целях этой конкретной проблемы, возможно ли вам немного рассказать о том, как ее реализовать? Хотя это выглядит более обширно, чем регулярное выражение, это звучит как интересный подход, который я хотел бы попробовать. Ian
2

или вы хотите сохранить больше комментариев, которые вы могли бы использоватьpreg_replace_callback, Затем вы можете определить функцию для обработки комментариев по отдельности.

<?php
function callback($buffer) {
    return preg_replace_callback('/<!--.*-->/U', 'comment_replace_func', $buffer);
}

function comment_replace_func($m) {
    if (preg_match( '/^\<\!--\[if \!/i', $m[0])) {
        return $m[0];   
    }              

    return '';
}   

ob_start("callback");
?>

... HTML source goes here ...

<?php ob_end_flush(); ?>
Правильно ли я считаю, что скрипт должен быть вставлен в голову следующим образом: & lt;? Php $ result = preg_replace_callback (& amp; / & lt;! -. * - & gt; / U & apos ;, comment_replace_func & apos ;, $ buffer ); function comment_replace_func ($ m) {if (preg_match ('/ ^ \ & lt; \! - [if \! / i', $ m [0])) {return $ m [0]; } return & apos ;; } ob_start (& quot; callback & quot;); ? & GT; ... исходный код HTML находится здесь ... & lt;? Php ob_end_flush (); ? & GT; Если это так, это не удаляет какие-либо комментарии или, по-видимому, имеет какой-либо эффект? Ian
1

<?php
  function callback($buffer) {
    return preg_replace('/<!--[^\[](.|\s)*?-->/', '', $buffer);
  }
  ob_start("callback");
?>
... HTML source goes here ...
<?php ob_end_flush(); ?>

Он удаляет все комментарии и оставляет условные выражения, за исключением верхнего:

<!--[if !IE]><!-->
<link rel="stylesheet" href="/css/screen.css" type="text/css" media="screen" />
<!-- <![endif]-->

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

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

Решение Томалака выглядит хорошо, но как новичок и никаких дальнейших руководящих принципов я не знаю, как его реализовать, хотя я хотел бы попробовать, если кто-нибудь может уточнить, как его применять?

Спасибо

0

Нечто подобное может работать:

/<!--[^\[](.|\s)*?-->/

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

Вы называете это так? (не уверен, что этот код будет публиковаться в комментариях) ;
Хм ... я запускаю это здесь:solmetra.com/scripts/regex/index.php используя параметр preg_replace, я вырезал и вставил ваш фрагмент кода: он оставляет там условные выражения.
Я изменю ответ, включив в него начальный и конечный символы ...
Привет, Боден. Этот метод удаляет комментарий, но оставляет & lt; & gt; это означает, что таблицы стилей не применяются, а документ заполнен стрелками. Ian
Да, вся строка: return preg_replace ("/ & lt;! - [^ [] (. | \ S) *? - & gt; /"; "," буфер "); Теперь это не оставляет скобок, но не оставляет условных комментариев также: & lt;! - [if! IE] & gt; & lt;! - [if IE 7] & gt; & lt; link rel = & quot; таблица стилей & quot; HREF = & Quot; /templates/css/ie7.css" тип = & Quot; текст / CSS & Quot; СМИ = & Quot; Экран & Quot; / & GT; & Lt;! [ENDIF] & GT; & lt;! - [если IE 6] & gt; & lt; link rel = & quot; таблица стилей & quot; HREF = & Quot; /templates/css/ie6.css" тип = & Quot; текст / CSS & Quot; СМИ = & Quot; Экран & Quot; / & GT; & Lt; [ENDIF] - & GT!; & lt; link rel = & quot; таблица стилей & quot; тип = & Quot; текст / CSS & Quot; СМИ = & Quot; печать & Quot; HREF = & Quot; /templates/css/print.css" / & GT; Ian

Похожие вопросы