Textsuche
Der Textmodus von Greph durchsucht einen durchsuchten Dateibaum zeilenweise nach Bytes. Er ist der Standardmodus der greph-CLI und der Greph::searchText()-Fassade. Die Ausgabe verwendet das kanonische Format file:line:content, das grep, ripgrep und die meisten Editorintegrationen verarbeiten können.
Schnellbeispiele
# 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
Muster
Standardmäßig wird das Muster als regulärer PCRE2-Ausdruck behandelt. Die Funktionen preg_* von PHP bilden die Grundlage der Engine, daher entspricht die Syntax der PHP PCRE-Referenz.
Deaktiviere die Regex-Engine mit -F, um das Muster als literale Bytefolge zu behandeln. Der Modus für feste Zeichenfolgen ist der schnelle Pfad: Er verwendet strpos() für den Abgleich und überspringt den PCRE2-Kompilierschritt vollständig.
-i macht beide Modi unabhängig von Groß- und Kleinschreibung. -w fügt auf beiden Seiten des Treffers Wortgrenzen hinzu.
Dateien filtern
Greph durchläuft den Dateibaum vor der Suche. Der Datei-Scanner wird mit dem AST-Modus und dem Indexmodus geteilt, daher gelten dieselben Filteroptionen überall.
| Option | Wirkung |
|---|---|
--type NAME |
Nur Dateien einschließen, die dem benannten Typalias entsprechen (php, js, md, ...) |
--type-not NAME |
Dateien ausschließen, die dem benannten Typalias entsprechen |
--glob GLOB |
Nur Dateien einschließen, deren Pfade auf GLOB passen. Wiederholbar. |
--no-ignore |
.gitignore oder .grephignore nicht beachten |
--hidden |
Versteckte Dateien einschließen |
Der Datei-Scanner beachtet standardmäßig .gitignore und .grephignore, überspringt Binärdateien (erkannt anhand von Nullbytes in den ersten 512 Bytes) und begrenzt die Dateigröße auf 10 MiB. Beide Grenzwerte lassen sich über WalkOptions konfigurieren.
Eine vollständige Liste der integrierten Typaliasse findest du unter API / FileTypeFilter.
Kontext, Trefferzahlen und reine Dateimodi
# 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 und -L umgehen den Formatierer direkt und vermeiden so, jede Zeile im Speicher abzulegen. Sie eignen sich für Abfragen wie „wie viele“ und „wo“.
Parallele Scans
Übergib -j N, um den Scan auf N Worker zu verteilen. Greph verwendet pcntl_fork() für den Worker-Pool und greift auf die Ausführung in einem einzelnen Prozess zurück, wenn ext-pcntl nicht verfügbar ist.
./vendor/bin/greph -F -j 8 "function" src
Die Fassade berechnet anhand der Dateianzahl, des Modus und der Musterform, ob sich parallele Ausführung lohnt. Unterhalb des Schwellenwerts bleibt sie bei einem einzelnen Prozess. Die Heuristiken findest du unter Advanced / Parallel Workers.
JSON-Ausgabe
--json gibt eine strukturierte Nutzlast aus, die nachgelagerte Werkzeuge ohne Auslesen des Bildschirmausgabeformats von grep verarbeiten können:
./vendor/bin/greph --json -F "function" src
[
{
"file": "src/Greph.php",
"matches": [
{
"line": 31,
"column": 1,
"content": "final class Greph",
"matched_text": "function",
"captures": []
}
]
}
]
Der Wrapper rg gibt stattdessen Ereignisse im Format von ripgrep als JSON aus. Verwende ihn, wenn ein vorhandener Verbraucher das ripgrep-Schema erwartet.
Programmatische Verwendung
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";
}
}
Die Ergebnisobjekte sind unter API / Result objects dokumentiert.
So funktioniert es
Die Text-Engine hat zwei Pfade:
- Literaler Pfad: Wenn
-Fgesetzt ist, durchsuchtstrpos()einen 64-KiB-gepufferten Reader und erfasst Zeilenumbrüche zur Zeilennummerierung. Es gibt keinen Schritt zum Kompilieren eines regulären Ausdrucks. - Regex-Pfad: Wenn
-Fnicht gesetzt ist, extrahiert Greph mit einem kleinen PCRE-ähnlichen Analysator (Greph\Text\LiteralExtractor) literale Teilzeichenfolgen aus dem Muster und verwendet sie alsstrpos()-Vorfilter. Zeilen, die den Vorfilter passieren, werden anschließend mit dem kompilierten PCRE2-Muster und aktiviertem JIT abgeglichen.
Beide Pfade verwenden dasselbe BufferedReader für die Ein-/Ausgabe. Der Reader liest Daten in 64-KiB-Blöcken statt fgets() pro Zeile, wodurch die Anzahl der Systemaufrufe bei großen Dateien deutlich sinkt.
Bei wiederholten Arbeitslasten ersetzt der indexierte Textmodus den gepufferten Reader durch einen aufgewärmten Trigramm- und Bezeichner-Posting-Speicher und überspringt die meisten Dateien vollständig.