use*_*374 5 php regex preg-match preg-split
我有一个混有HTML的php页面.一些示例代码:
<?php echo "<p>some text</p>"; ?>/* <? some php in comments ?> */
<p>some HTML text</p> <!-- <h1>some HTML in comments</h1> -->
<? $header_info = <<<END
\$some="<?php @ob_start(); @session_set_save_handler(); ?>";
END; ?>
<h2>Some more HTML</h2>
Run Code Online (Sandbox Code Playgroud)
我想在每个PHP和HTML标记处拆分,但保留/忽略引号或注释中的任何PHP标记或HTML标记.这是我到目前为止:
$array = preg_split("/((^<\?php)|([^'|\"]<\?php)|([^'|\"]<\?)|([^'|\"]\?>)|(<\%)|(\%>))/i", $string, -1);
Run Code Online (Sandbox Code Playgroud)
我遇到的问题是最终的$数组中缺少一些HTML结束括号'>'.我想保持HTML打开和关闭标签完好无损.有时我最终会
<p></p instead of <p></p>
Run Code Online (Sandbox Code Playgroud)
它应该如下所示:
[0] echo "<p>some text</p>";
[1] <p>some HTML text</p>
[2] $header_info = <<<END
\$some="<?php @ob_start(); @session_set_save_handler(); ?>";
END;
[3] <h2>Some more HTML</h2>
Run Code Online (Sandbox Code Playgroud)
只要preg_split没有将它们视为任何分隔符并忽略它们中的任何一个,任何注释都不需要成为数组的一部分.
我也刚刚意识到一些php标签,特别是在使用eval()时最终会像这样结束:
"?> <p>some HTML text</p> <?";
Run Code Online (Sandbox Code Playgroud)
这意味着我的正则表达式中的引用与任何这些情况都不匹配.
Preg_match()可能是一个更好的选择,但不确定.
任何帮助都会非常感激,因为我在正则表达方面并不是非常聪明,而是在这一点上陷入困境.
非常感谢 :)
前言
由于询问了正则表达式解决方案,因此以下解决方案将依赖于正则表达式。然而,在这种特殊情况下,PHP 解析器会更适合。
正则表达式
#(?<!"|\')<\\?(?:php)?\\s+(.+?)\\?>(?!"|\')|/\*.+\*/|<!--.+-->#is
Run Code Online (Sandbox Code Playgroud)
小脚本
$subject = '<?php echo "<p>some text</p>"; ?>/* <? some php in comments ?> */
<p>some HTML text</p> <!-- <h1>some HTML in comments</h1> -->
<? $header_info = <<<END
\\$some="<?php @ob_start(); @session_set_save_handler(); ?>";
END; ?>
<h2>Some more HTML</h2>';
$returnValue = preg_replace('#(?<!"|\')<\\?(?:php)?\\s+(.+?)\\?>(?!"|\')|/\*.+\*/|<!--.+-->#is', '$1', $subject, -1);
var_dump(preg_split('#\\r?\\n#s', $returnValue));
Run Code Online (Sandbox Code Playgroud)
结果
array(6) {
[0]=>
string(25) "echo "<p>some text</p>"; "
[1]=>
string(22) "<p>some HTML text</p> "
[2]=>
string(21) "$header_info = <<<END"
[3]=>
string(60) "\$some="<?php @ob_start(); @session_set_save_handler(); ?>";"
[4]=>
string(5) "END; "
[5]=>
string(23) "<h2>Some more HTML</h2>"
}
Run Code Online (Sandbox Code Playgroud)
演示
http://sandbox.onlinephpfunctions.com/code/017a51877b50f272f151feade7b59e142757481e
讨论
1. #
2. (?<!"|\')
3. <\\?(?:php)?\\s+
4. (.+?)
5. \\?>
6. (?!"|\')
7. |/\*.+\*/
8. |<!--.+-->
9. #is
Run Code Online (Sandbox Code Playgroud)
第 1 行我使用这个正则表达式分隔符,因为它可以避免 /
第 2 行的转义这是正则表达式的关键。负向后查找用于确保下一个打开的 php 标记前面没有任何单引号或双引号。
第 3 行这里定义了 php 起始标签。为了也支持 ASP 标签,可以像这样更改此行:<\\?(?:php|%)?\\s+
第 4 行由于我们已经检测到 php 代码序列的开始,因此我们匹配此 php 代码序列中出现的任何字符。请注意,在第 9 行,我们使用s标志来表明我们也需要在 php 代码序列中添加新行。
第 5 行我们标记 php 代码序列的结尾。
第 6 行我们确保前面匹配的 php 标签后面没有任何带有否定先行断言的单/双引号。
第 7,8 行如果我们发现一些 php/HTML 注释,它们将被简单地忽略。
第 9 行结束 f 正则表达式。
已知的问题
$subject,行只是用换行符(前面有可选的回车符)分隔符分隔。