
# Търсене в текст

Текстовият режим на Greph търси ред по ред байтове в обходено дърво от файлове. Това е режимът по подразбиране на `greph` CLI и фасадата `Greph::searchText()`. Изходът е в каноничния формат `file:line:content`, който се обработва от grep, ripgrep и повечето интеграции с редактори.

## Кратки примери

```bash
# 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. Функциите `preg_*` на PHP осигуряват енджина, така че синтаксисът съответства на [справочника за PCRE на PHP](https://www.php.net/manual/en/pcre.pattern.php).

Изключете енджина за регулярни изрази с `-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](https://greph.inline0.dev/bg/docs/api#grephwalkerfiletypefilter) за пълния списък с вградени псевдоними на типове.

## Контекст, бройки и режими само за файлове

```bash
# 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` не е налично.

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

Фасадата изчислява дали паралелното изпълнение си заслужава допълнителните разходи въз основа на броя файлове, режима и формата на шаблона. Под прага остава в един процес. Вижте [Разширени настройки / Паралелни работни процеси](https://greph.inline0.dev/bg/docs/advanced/parallel) за евристиките.

## Изход във формат JSON

`--json` извежда структурирани данни, които следващите инструменти могат да обработят, без да извличат данни от екрана във формата на grep:

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

Обвивката `rg` вместо това извежда JSON във формат на събития ripgrep. Използвайте я, когато съществуващ потребител очаква схемата ripgrep.

## Програмно използване

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

Обектите с резултати са описани в [API / Обекти с резултати](https://greph.inline0.dev/bg/docs/api#result-objects).

## Как работи

Текстовият енджин има два пътя:

- **Буквален път**: когато е зададено `-F`, търсенето се изпълнява с `strpos()` върху буфериран четец с размер 64 KiB и се следят новите редове за номериране на редовете. Компилиране на регулярни изрази не се извършва.
- **Път с регулярни изрази**: когато `-F` не е зададено, Greph извлича буквални поднизове от шаблона чрез малък анализатор в стил PCRE (`Greph\Text\LiteralExtractor`) и ги използва като предварителен филтър `strpos()`. След това редовете, преминали предварителния филтър, се проверяват спрямо компилирания шаблон PCRE2 с активиран JIT.

И двата пътя използват един и същ `BufferedReader` за входно-изходните операции. Четецът чете на блокове от 64 KiB вместо `fgets()` на ред, което драстично намалява броя системни извиквания при големи файлове.

При повтарящи се задачи [индексираният текстов режим](https://greph.inline0.dev/bg/docs/indexed/text) заменя буферирания четец с предварително заредено хранилище за триграми и публикации на идентификатори и пропуска повечето файлове изцяло.
