Przejdź do treści

Wyszukiwanie tekstu

Tryb tekstowy Greph wyszukuje bajty wiersz po wierszu w przemierzanym drzewie plików. Jest domyślnym trybem greph CLI oraz fasady Greph::searchText(). Wyniki są w kanonicznym formacie file:line:content, który analizują grep, ripgrep i większość integracji z edytorami.

Szybkie przykłady

Powłoka
# 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

Wzorce

Domyślnie wzorzec jest traktowany jako wyrażenie regularne PCRE2. Za silnikiem stoją funkcje preg_* z PHP, więc składnia odpowiada dokumentacji PCREPHP.

Wyłącz silnik wyrażeń regularnych za pomocą -F, aby traktować wzorzec jako dosłowną sekwencję bajtów. Tryb stałego ciągu to szybka ścieżka: do dopasowywania używa strpos() i całkowicie pomija etap kompilacji PCRE2.

-i sprawia, że w obu trybach wielkość liter nie ma znaczenia. -w dodaje granice całych słów po obu stronach dopasowania.

Filtrowanie plików

Greph przemierza drzewo plików przed wyszukiwaniem. Ten sam mechanizm przemierzania jest używany w trybie AST i trybie indeksowanym, dlatego wszędzie obowiązują te same flagi filtrowania.

Flaga Działanie
--type NAME Uwzględnia tylko pliki pasujące do nazwanego aliasu typu (php, js, md, ...)
--type-not NAME Wyklucza pliki pasujące do nazwanego aliasu typu
--glob GLOB Uwzględnia tylko pliki, których ścieżki pasują do GLOB. Można powtarzać.
--no-ignore Ignoruje .gitignore lub .grephignore
--hidden Uwzględnia ukryte pliki

Mechanizm przemierzania domyślnie respektuje .gitignore i .grephignore, pomija pliki binarne (wykrywane na podstawie bajtów null w pierwszych 512 bajtach) i ogranicza rozmiar pliku do 10 MiB. Oba limity można skonfigurować za pomocą WalkOptions.

Pełną listę wbudowanych aliasów typów znajdziesz w API / FileTypeFilter.

Kontekst, liczniki i tryby tylko dla plików

Powłoka
# 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 i -L pomijają formatowanie, dzięki czemu nie trzeba wczytywać wszystkich wierszy do pamięci. To odpowiednie tryby dla zapytań „ile” i „gdzie”.

Skanowanie równoległe

Przekaż -j N, aby rozdzielić skanowanie między N procesów roboczych. Greph używa pcntl_fork() do utworzenia puli procesów roboczych i przechodzi na wykonanie jednego procesu, gdy ext-pcntl jest niedostępne.

Powłoka
./vendor/bin/greph -F -j 8 "function" src

Fasada ocenia, czy wykonanie równoległe jest warte dodatkowego narzutu, na podstawie liczby plików, trybu i kształtu wzorca. Poniżej progu pozostaje przy jednym procesie. Zobacz Zaawansowane / Procesy robocze równoległe, aby poznać heurystyki.

Dane wyjściowe JSON

--json emituje uporządkowany ładunek danych, który narzędzia dalszego przetwarzania mogą analizować bez pobierania wyników w formacie grep:

Powłoka
./vendor/bin/greph --json -F "function" src
JSON
[
  {
    "file": "src/Greph.php",
    "matches": [
      {
        "line": 31,
        "column": 1,
        "content": "final class Greph",
        "matched_text": "function",
        "captures": []
      }
    ]
  }
]

Opakowanie rg emituje zamiast tego JSON w formie zdarzeń ripgrep. Użyj go, gdy istniejący odbiorca oczekuje schematu ripgrep.

Użycie programowe

PHP
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";
    }
}

Obiekty wynikowe opisano w API / Obiekty wynikowe.

Jak to działa

Silnik tekstowy ma dwie ścieżki:

  • Ścieżka dosłowna: gdy ustawiono -F, wyszukiwanie wykonuje strpos() na buforowanym czytniku o rozmiarze 64 KiB i śledzi znaki nowej linii na potrzeby numeracji wierszy. Nie ma etapu kompilacji wyrażeń regularnych.
  • Ścieżka wyrażeń regularnych: gdy nie ustawiono -F, Greph wyodrębnia dosłowne podciągi ze wzorca za pomocą prostego analizatora w stylu PCRE (Greph\Text\LiteralExtractor) i używa ich jako filtra wstępnego strpos(). Wiersze, które przejdą filtr wstępny, są następnie dopasowywane do skompilowanego wzorca PCRE2 z włączonym JIT.

Obie ścieżki używają tego samego BufferedReader do operacji wejścia i wyjścia. Czytnik odczytuje dane w porcjach po 64 KiB zamiast fgets() na wiersz, co znacznie zmniejsza liczbę wywołań systemowych w przypadku dużych plików.

Przy powtarzających się zadaniach indeksowany tryb tekstowy zastępuje buforowany czytnik rozgrzanym magazynem trójgramów i wystąpień identyfikatorów, całkowicie pomijając większość plików.