Поиск по тексту
Текстовый режим Greph выполняет построчный поиск байтов в обходе дерева файлов. Это режим по умолчанию для greph CLI и фасада Greph::searchText(). Вывод использует канонический формат file:line:content, который разбирают grep, ripgrep и большинство интеграций с редакторами.
Краткие примеры
# Regex search across the current directory
./vendor/bin/greph "function\s+\w+"
# Fixed-string search across src/
./vendor/bin/greph -F "function" src
# Case-insensitive whole-word search
./vendor/bin/greph -F -i -w "function" src
# Two lines of context around each match
./vendor/bin/greph -F -C 2 "TODO" src
# Stop after the first three matches per file
./vendor/bin/greph -F -m 3 "TODO" src
# Files that contain the pattern
./vendor/bin/greph -F -l "TODO" src
# Files that do not contain the pattern
./vendor/bin/greph -F -L "TODO" src
# Count matches per file
./vendor/bin/greph -F -c "TODO" src
# Inverted match
./vendor/bin/greph -F -v "TODO" src/notes.txt
Паттерны
По умолчанию шаблон считается регулярным выражением PCRE2. Функции PHPpreg_* лежат в основе движка, поэтому синтаксис соответствует справочнику по PCREPHP.
Отключите движок регулярных выражений с помощью -F, чтобы трактовать шаблон как буквальную последовательность байтов. Режим точного совпадения — быстрый путь: для поиска он использует strpos() и полностью пропускает этап компиляции PCRE2.
-i включает нечувствительность к регистру в обоих режимах. -w добавляет границы целого слова с обеих сторон совпадения.
Фильтрация файлов
Greph обходит дерево файлов перед поиском. Механизм обхода общий для режимов AST и индексированного поиска, поэтому одни и те же флаги фильтрации действуют везде.
| Флаг | Эффект |
|---|---|
--type NAME |
Включать только файлы с указанным псевдонимом типа (php, js, md, ...) |
--type-not NAME |
Исключать файлы с указанным псевдонимом типа |
--glob GLOB |
Включать только файлы, пути которых соответствуют GLOB. Флаг можно повторять. |
--no-ignore |
Не учитывать .gitignore или .grephignore |
--hidden |
Включать скрытые файлы |
По умолчанию механизм обхода учитывает .gitignore и .grephignore, пропускает бинарные файлы (определяет их по нулевым байтам в первых 512 байтах) и ограничивает размер файлов до 10 MiB. Оба ограничения можно настроить через WalkOptions.
Полный список встроенных псевдонимов типов см. в API / FileTypeFilter.
Контекст, счётчики и режимы только для файлов
# Two lines before and after each match
./vendor/bin/greph -F -C 2 "needle" src
# Two lines after, no lines before
./vendor/bin/greph -F -A 2 "needle" src
# Two lines before, no lines after
./vendor/bin/greph -F -B 2 "needle" src
# Count matches per file
./vendor/bin/greph -F -c "needle" src
# List matching files only
./vendor/bin/greph -F -l "needle" src
# List non-matching files only
./vendor/bin/greph -F -L "needle" src
-c, -l и -L сразу обходят форматировщик, поэтому не создают объекты для каждой строки. Эти режимы подходят для запросов «сколько» и «где».
Параллельное сканирование
Передайте -j N, чтобы распределить сканирование между N рабочими процессами. Greph использует pcntl_fork() для пула рабочих процессов и переходит к выполнению в одном процессе, если ext-pcntl недоступен.
./vendor/bin/greph -F -j 8 "function" src
Фасад определяет, оправдан ли накладной расход на параллельное выполнение, исходя из числа файлов, режима и структуры шаблона. Ниже порога он остаётся в однопроцессном режиме. Эвристики описаны в разделе Дополнительно / Параллельные рабочие процессы.
Вывод JSON
--json выдаёт структурированные данные, которые последующие инструменты могут разбирать без снятия данных с экрана из формата grep:
./vendor/bin/greph --json -F "function" src
[
{
"file": "src/Greph.php",
"matches": [
{
"line": 31,
"column": 1,
"content": "final class Greph",
"matched_text": "function",
"captures": []
}
]
}
]
Обёртка rg вместо этого выдаёт ripgrep в виде событий JSON. Используйте её, если существующий потребитель ожидает схему ripgrep.
Программное использование
use Greph\Greph;
use Greph\Text\TextSearchOptions;
$results = Greph::searchText(
'function',
'src',
new TextSearchOptions(
fixedString: true,
caseInsensitive: true,
beforeContext: 1,
afterContext: 1,
jobs: 4,
),
);
foreach ($results as $file) {
foreach ($file->matches as $match) {
echo "{$file->file}:{$match->line}:{$match->content}\n";
}
}
Описание объектов результатов см. в API / Объекты результатов.
Как это работает
У текстового движка есть два пути:
- Путь точных совпадений: если задан
-F, поиск выполняетсяstrpos()через буферизованный считыватель на 64 KiB с отслеживанием переводов строк для нумерации. Этап компиляции регулярного выражения отсутствует. - Путь регулярных выражений: если
-Fне задан, Greph извлекает из шаблона буквальные подстроки с помощью небольшого анализатора в стиле PCRE (Greph\Text\LiteralExtractor) и использует их как предварительный фильтрstrpos(). Строки, прошедшие фильтр, затем проверяются скомпилированным шаблоном PCRE2 с включённым JIT.
Для ввода-вывода оба пути используют один и тот же BufferedReader. Считыватель читает данные блоками по 64 KiB вместо чтения fgets() для каждой строки, что значительно сокращает число системных вызовов на больших файлах.
Для повторяющихся задач режим индексированного текста заменяет буферизованный читатель прогретым хранилищем триграмм и публикаций идентификаторов, пропуская большую часть файлов целиком.