PHPでHTMLコメントを削除するが、条件を残す
-
06-07-2019 - |
質問
現在、ページからすべてのHTMLコメントを取り除くためにPHPと正規表現を使用しています。スクリプトは上手く機能します...少し上手すぎます。条件付きコメントを含むすべてのコメントを削除します。ここに私が持っているものがあります:
<?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]-->
<!--[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は実際の一致を引き起こします。
&quot; global&quot;で適用および「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は、「downlevel-revealed」」のためです。構文は、次を参照してください:&quot; MSDN-条件付きコメントについて&quot; 。
スペースが許可または予想される場所が完全にはわかりません。必要に応じて、式に \ s *
を追加します。
他のヒント
1つの正規表現で動作しない場合、またはコメントをさらに保存したい場合は、を使用できます 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の正規表現エンジンが次のようになるかどうかはわかりませんが、このパターンを試してください:
'/<!--(.|\s)*(\[if .*\]){0}(.|\s)*?-->/'
このような何かが機能する可能性があります:
/<!--[^\[](.|\s)*?-->/
コメントは無視されますが、コメント開始タグの直後に開き括弧が付いている点を除いて、あなたのものと同じです。