我需要一个可以从HTML文件修剪PHP的内衬。诀窍在于我还需要它来保留以前由PHP行占用的新行。
php -r "echo preg_replace('/<\\\\?.*(\\\\?>|\$)/Us','', file_get_contents(\$argv[1]));" -- "./index.php"
这“有效”但不保留新行,例如:
<html><?php test(); ?>
<head>
<?php test();
?>
</head>
<body>
</body>
<html>
解析为:
<html>
<head>
</head>
<body>
</body>
<html>
但我需要它来解决:
<html>
<head>
</head>
<body>
</body>
<html>
也许我正在使用锤子驱动螺丝,但我想要做的是删除PHP代码,通过htmlhint运行结果并使报告的行号实际上与文件中的行匹配。
如果有更好的解决方案,我很乐意听到。最终目标是将具有PHP,Javascript和HTML混合的文件与各自的链接组合在一起。
答案 0 :(得分:2)
正则表达式绝对不是这个问题的最佳答案,但是因为您正在以正则表达式形式寻找答案,所以您拥有它!
注意:如果评论或字符串包含<?
,则会中断。
(?:\G(?!\A)|\h*(?=<\?))(.*(?=(?:(?!<\?)[\s\S])*?(?<=\?>)))
<html><?php test(); ?>
<head>
<?php test();
?>
</head>
<body>
</body>
<html>
<html>
<head>
</head>
<body>
</body>
<html>
(?:\G(?!\A)|\h*(?=<\?))
匹配以下任一选项
\G(?!\A)
\G
在上一场比赛结束时断言位置或第一场比赛的字符串开头(?!\A)
否定前瞻声明后面的内容不是字符串的开头(这基本上使\G
仅匹配上一个匹配的结尾)\h*(?=<\?)
符合以下条件
\h*
匹配任意数量的水平空格(用于在<?
(?=<\?)
确定以下匹配的积极前瞻
<
字面匹配小于<
字符\?
字面上匹配问号字符?
(.*(?=(?:(?!<\?)[\s\S])*?(?<=\?>)))
将以下内容捕获到捕获组1中
.*
任意次数匹配任何字符(行终止符除外)(?=(?:(?!<\?)[\s\S])*?(?<=\?>))
确定后续匹配的正向前瞻
(?:(?!<\?)[\s\S])*?
匹配以下任意次数,但尽可能少
(?!<\?)
否定前瞻确保后续内容不匹配
<
字面匹配小于<
字符\?
字面上匹配问号字符?
[\s\S]
匹配任何字符(?<=\?>)
负面的背后隐藏确保先于什么匹配以下内容
\?
字面上匹配问号字符?
>
字面匹配大于>
字符答案 1 :(得分:0)
使用tokenizer (内部丑陋的东西):
确定一行php -r 'echo array_reduce(token_get_all(file_get_contents($argv[1])),function($c,$i){return $i[0]==321?$c.$i[1]:$c.str_repeat("\n",@count_chars($i.$i[1])[10]);});'
标记化程序的优点:即使像"abc <?php echo '?>'; ?> def"
这样的字符串也能正确解析。
321是常量T_INLINE_HTML
的值(所有不在php标记之间)。
10是换行符(LF)的ASCII码。 (默认情况下,count_chars
返回一个关联数组,其中ASCII代码为键,出现次数为值)。
丑陋的东西是$i.$i[1]
,它将数组与字符串或带有未定义内容的字符串连接起来。 @
避免发出警告和通知。无论如何,这个技巧避免了测试,并且保留了换行符的数量。 (请参阅返回token_get_all
以了解问题的原因)。
或DOMDocument
:
php -r '$d=DOMDocument::loadHTMLFile($argv[1],8196);foreach((new DOMXPath($d))->query("//processing-instruction()")as$p)$p->parentNode->replaceChild($d->createTextNode(preg_replace("~\S+~","",$p->nodeValue)),$p);echo$d->saveHTML();'