HTML 주석을 PHP로 제거하지만 조건부를 남기십시오
-
06-07-2019 - |
문제
현재 PHP와 정규 표현식을 사용하여 페이지에서 모든 HTML 댓글을 제거하고 있습니다. 스크립트는 잘 작동합니다 ... 조금 잘 작동합니다. 그것은 내 조건부 의견을 포함하여 모든 의견을 제거합니다. 내가 가진 것들은 다음과 같습니다.
<?php
function callback($buffer)
{
return preg_replace('/<!--(.|\s)*?-->/', '', $buffer);
}
ob_start("callback");
?>
... HTML source goes here ...
<?php ob_end_flush(); ?>
내 regex가 너무 뜨겁지 않기 때문에 다음과 같은 조건부 의견을 배제하기 위해 패턴을 수정하는 방법을 알아내는 데 어려움을 겪고 있습니다.
<!--[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]-->
건배
해결책
댓글은 HTML에 중첩 될 수 없으므로 이론적으로 동정인은 작업을 수행 할 수 있습니다. 그럼에도 불구하고, 어떤 종류의 파서를 사용하는 것이 더 나은 선택이 될 것입니다. 특히 입력이 잘 구성되지 않은 경우.
여기 내 시도가 있습니다. 정상적인 의견 만 일치시키기 위해서는 효과가 있습니다. 그것은 꽤 괴물이되었습니다. 죄송합니다. 나는 그것을 매우 광범위하게 테스트했지만 잘하는 것처럼 보이지만 보증은 제공하지 않습니다.
<!--(?!\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은 실제 일치를 원합니다.
"Global"및 "DotAll"플래그를 적용하십시오.
반대 (조건부 의견 만 일치)를 수행하려면 다음과 같습니다.
<!(--)?(?=\[)(?:(?!<!\[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)
다시, "글로벌"및 "dotall"플래그를 적용하십시오.
단계 #02는 "다운 레벨 리베일드"구문 때문입니다. "MSDN- 조건부 의견에 대해".
나는 공간이 허용되거나 예상되는 곳을 완전히 확신하지 못한다. 추가하다 \s*
적절한 표현에.
다른 팁
하나의 정규 표현으로 작업 할 수 없거나 사용할 수있는 더 많은 의견을 보존하려는 경우 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(); ?>
요약하면 이것은 최상의 솔루션 인 것 같습니다.
<?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]-->
추가로 문제가 발생하는 것 같습니다.
누구든지 이것을 고려하고 그 신분을 제자리에 두는 정규식을 제안 할 수 있다면 그것은 완벽 할 것입니다.
Tomalak의 솔루션은 좋아 보이지만 초보자와 더 이상 지침이없는 사람은 누구나 적용하는 방법에 대해 자세히 설명 할 수 있다면 시도해보고 싶지만 구현 방법을 모르겠습니까?
감사
PHP의 Regex 엔진이 다음과 같은 것을 좋아할지 확실하지 않지만이 패턴을 시도해보십시오.
'/<!--(.|\s)*(\[if .*\]){0}(.|\s)*?-->/'
이와 같은 것이 효과가있을 수 있습니다.
/<!--[^\[](.|\s)*?-->/
주석 시작 태그 직후에 주석이 오프닝 브래킷을 가지고 있다는 것을 제외하고는 당신과 동일합니다.