Извлечь все комментарии из PHP-файла: token_get_all и потоковый ввод
Зачем это вообще
В легаси‑коде, агенте или кастомном модуле «1С‑Битрикс» комментарии часто живут дольше, чем живой контекст: там остаются временные объяснения, отключённые куски и PHPDoc, который IDE уже не показывает. Если нужен быстрый снимок «по тексту без исполнения кода», удобнее не регулярками вырезать /* … */, а пройти токены так, как делает парсер PHP.
Лексический разбор: token_get_all
Функция token_get_all($source) возвращает массив токенов. Каждый элемент либо массив [id, текст, строка], либо одиночная строковая пунктуация вида ; или {. Комментарии приходят как T_COMMENT (одно- и многострочные в актуальных версиях) и как T_DOC_COMMENT для PHPDoc-блоков. В PHP 8+ набора типов уже меньше, чем во времена PHP 4 (T_ML_COMMENT больше не используется) — этого достаточно для задачи выборки текстов комментариев.
Скрипт: читаем файл из stdin
Так можно подставлять «кот» из нескольких файлов или использовать тот же бинарь в пайплайне CI. Обратите внимание: буфер исходного текста нужно явно обнулить, и массив с типами комментариев лучше проверять в строгом режиме in_array(..., true), чтобы не поймать неожиданное приведение типов.
declare(strict_types=1);
final class StreamCommentHarvest
{
private string $aggregate = '';
/* идентификаторы T_COMMENT и T_DOC_COMMENT */
private const INTERESTING = [
T_COMMENT,
T_DOC_COMMENT,
];
public function consumeStdin(): void
{
$stdin = fopen('php://stdin', 'rb');
if ($stdin === false) {
throw new RuntimeException('Cannot open stdin');
}
try {
while (!feof($stdin)) {
$chunk = fread($stdin, 8192);
if ($chunk === false) {
break;
}
if ($chunk !== '') {
$this->aggregate .= $chunk;
}
}
} finally {
fclose($stdin);
}
}
/**
* Список фрагментов исходника, помеченных как комментарии.
*/
public function collectCommentBodies(): array
{
if ($this->aggregate === '') {
return [];
}
$pieces = token_get_all($this->aggregate);
$out = [];
foreach ($pieces as $item) {
if (!is_array($item)) {
continue;
}
[$id, $text] = [$item[0], $item[1]];
if (!in_array($id, self::INTERESTING, true)) {
continue;
}
$out[] = $text;
}
return $out;
}
public function printBodies(): void
{
foreach ($this->collectCommentBodies() as $block) {
echo $block, PHP_EOL;
}
}
}
$harvest = new StreamCommentHarvest();
$harvest->consumeStdin();
$harvest->printBodies();Запуск
Один файл:
php extract-comments.php < local/modules/itd.vendor/lib/LegacyFacade.phpНебольшой дерево обход через find — помните о кавычках и ограничениях командной строки; для глубоких проектов логичнее сначала сформировать список файлов и читать их по одному через PHP или xargs с ограничением параллелизма, чтобы не упираться в квоты.
Чего инструмент не делает
- Комментарии внутри строковых литералов и интерполяций здесь считаются обычным текстом строки — именно этого хочет язык при токенизации.
- «Мёртвый» код за
#ifв условной компиляции у PHP отсутствует; здесь просто текст исходника. - Для доверенного аудита секретов нужны отдельные проверки: комментарий не выполняется, но текст может содержать URL и пароли — вывод сохраняйте в файл с нужными правами.
Кратко
token_get_all даёт синтаксически честную выборку T_COMMENT/T_DOC_COMMENT; связка со stdin упрощает автоматизацию вокруг Битрикс‑дерева и легаси‑скриптов без подключения ядра.
Не хотите копаться сами?
Починю за 1-3 дня. Без предоплаты — оплата по результату.
15+ лет опыта с 1С-Битрикс · Без предоплаты · 7 дней гарантии