Hoppa till innehåll

Textsökning

Grephs textläge är en radbaserad bytesökning genom ett genomsökt filträd. Det är standardläget i greph CLI och fasaden Greph::searchText(). Utdata använder det kanoniska formatet file:line:content, som grep, ripgrep och de flesta editorintegrationer kan tolka.

Snabba exempel

Shell
# 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

Mönster

Som standard behandlas mönstret som ett reguljärt PCRE2-uttryck. PHPs preg_*-funktioner ligger till grund för motorn, så syntaxen motsvarar PHP PCRE-referensen.

Stäng av regexmotorn med -F för att behandla mönstret som en bokstavlig bytesekvens. Läget med fasta strängar är den snabba vägen: det använder strpos() för matchning och hoppar helt över PCRE2-kompileringen.

-i gör båda lägena skiftlägesokänsliga. -w lägger till ordgränser på båda sidor om matchningen.

Filtrera filer

Greph går igenom filträdet före sökningen. Filträdsvandraren delas med AST-läget och det indexerade läget, så samma filterflaggor gäller överallt.

Flagga Effekt
--type NAME Inkludera endast filer som matchar det namngivna typaliaset (php, js, md, ...)
--type-not NAME Exkludera filer som matchar det namngivna typaliaset
--glob GLOB Inkludera endast filer vars sökvägar matchar GLOB. Kan upprepas.
--no-ignore Följ inte .gitignore eller .grephignore
--hidden Inkludera dolda filer

Filträdsvandraren respekterar .gitignore och .grephignore som standard, hoppar över binärfiler (identifieras genom nollbyte bland de första 512 byten) och begränsar filstorleken till 10 MiB. Båda gränserna kan konfigureras via WalkOptions.

Se API / FileTypeFilter för en fullständig lista över inbyggda typalias.

Kontext, antal och lägen som endast visar filer

Shell
# 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 och -L hoppar över formateraren så att varje rad inte behöver skapas i minnet. De passar för frågor om ”hur många” och ”var”.

Parallella genomsökningar

Skicka med -j N för att fördela genomsökningen på N arbetare. Greph använder pcntl_fork() för arbetargruppen och återgår till körning i en process när ext-pcntl inte är tillgängligt.

Shell
./vendor/bin/greph -F -j 8 "function" src

Fasaden beräknar om parallell körning är värd omkostnaden utifrån antalet filer, läget och mönstrets form. Under tröskelvärdet körs allt i en process. Se Avancerat / Parallella arbetare för heuristiken.

Utdata från JSON

--json skickar ut en strukturerad nyttolast som nedströmsverktyg kan tolka utan att skrapa grep-formatet:

Shell
./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": []
      }
    ]
  }
]

Omslaget rg skickar i stället ut ripgrep-händelseformad JSON. Använd det när en befintlig konsument förväntar sig schemat ripgrep.

Programmatisk användning

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

Resultatobjekten beskrivs i API / Resultatobjekt.

Så fungerar det

Textmotorn har två sökvägar:

  • Bokstavlig sökväg: när -F är inställt körs sökningen strpos() genom en buffrad läsare på 64 KiB som håller reda på radbrytningar för radnumrering. Ingen regexkompilering görs.
  • Regexsökväg: när -F inte är inställt extraherar Greph bokstavliga delsträngar ur mönstret med en liten PCRE-formad analysator (Greph\Text\LiteralExtractor) och använder dem som ett strpos()-förfilter. Rader som passerar förfiltret matchas sedan mot det kompilerade PCRE2-mönstret med JIT aktiverat.

Båda sökvägarna använder samma BufferedReader för I/O. Läsaren läser i 64 KiB-block i stället för fgets() per rad, vilket minskar antalet systemanrop kraftigt för stora filer.

Vid upprepade arbetsbelastningar ersätter det indexerade textläget den buffrade läsaren med ett uppvärmt trigrambaserat index och ett index över identifierarträffar, och hoppar helt över de flesta filer.