Мне нужен один лайнер, который урезает PHP из файла HTML. Хитрость заключается в том, что мне также нужно, чтобы сохранить символы новой строки, ранее занятые строками 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 с соответствующими ссылками.
Хорошо, одна строка с использованием токенизатора (Гадкая вещь внутри):
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 — код ASCII для символа новой строки (LF). (по умолчанию, 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();'
Регулярное выражение определенно не лучший ответ для этой проблемы, но так как вы ищете ответ в форме регулярного выражения, вот оно!
Заметка: Это сломается, если комментарий или строка содержит <?
,
Смотрите это регулярное выражение в использовании здесь
(?:\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]
Подходим любой персонаж(?<=\?>)
Отрицательный взгляд позади, гарантирующий, что предшествующее соответствует следующему
\?
Сопоставить знак вопроса ?
в прямом смысле>
Матч больше, чем символ >
в прямом смысле