preg_replace многострочный матч, но сохранить новые строки

Мне нужен один лайнер, который урезает 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 с соответствующими ссылками.

0

Решение

Хорошо, одна строка с использованием токенизатора (Гадкая вещь внутри):

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();'
0

Другие решения

краткое

Регулярное выражение определенно не лучший ответ для этой проблемы, но так как вы ищете ответ в форме регулярного выражения, вот оно!

Заметка: Это сломается, если комментарий или строка содержит <?,


Код

Смотрите это регулярное выражение в использовании здесь

(?:\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] Подходим любой персонаж
      • (?<=\?>) Отрицательный взгляд позади, гарантирующий, что предшествующее соответствует следующему
        • \? Сопоставить знак вопроса ? в прямом смысле
        • > Матч больше, чем символ > в прямом смысле
2

По вопросам рекламы [email protected]