
# 快速入门

## 安装

通过 Composer 安装 Greph：

```bash
composer require greph/greph
```

这会在 `vendor/bin/` 中安装该库以及四个可执行文件：

- `greph`：原生文本搜索、AST 搜索和 AST 重写
- `greph-index`：预热文本索引、AST 事实索引和缓存的 AST 搜索
- `rg`：ripgrep 风格的兼容包装器
- `sg`：ast-grep 风格的兼容包装器

这些可执行文件可从项目的 `vendor/bin/` 中运行，因为 Greph 0.2.3。较早版本只能在 Greph 仓库的克隆目录中找到 Composer 自动加载器，因此至少需要该版本：

```bash
composer require greph/greph:^0.2.3
```

## 要求

- **PHP 8.2+**，用于只读类、枚举、首类可调用语法和构造函数属性提升
- **ext-json**，用于 JSON 输出和磁盘索引负载
- **ext-ctype**，用于模式和选项解析
- **ext-tokenizer**，用于 PHP-Parser 和 AST 预筛选器
- **ext-zlib**，用于缓存的 AST 存储（`greph-index ast-cache`）
- **nikic/php-parser**（作为 Composer 依赖自动安装）

`ext-json`、`ext-ctype` 和 `ext-tokenizer` 在几乎所有 PHP 构建中都已启用。`composer.json` 目前仅声明 `ext-json`（[#5](https://github.com/inline0/greph/issues/5)），因此当其他扩展缺失时，Composer 不会发出警告。

可选：

- **ext-pcntl**，用于并行扫描。缺少该扩展时，Greph 会平稳降级为单进程执行。
- 外部 `rg`、`grep` 和 `sg` 二进制文件，用于基准比较。运行时绝不需要它们。

搜索、重写和索引操作都不会调用 `proc_open()` 或 `shell_exec()`；只有并行扫描会派生进程，若没有 `pcntl_fork()`，则会回退到单进程。有关禁用 `proc_open()`、`shell_exec()` 或 `pcntl_fork()` 的主机，请参见 [进程受限的主机](https://greph.inline0.dev/zh/docs/advanced/process-restricted-hosts)。

## 你的第一次文本搜索

Greph 的默认模式是兼容 grep 的文本搜索：

```bash
vendor/bin/greph -F "function" src
```

输出使用规范的 `file:line:content` 格式，这是 grep、ripgrep 和大多数编辑器集成所期望的格式。

```text
src/Greph.php:41:    public static function walk(string|array $paths, ?WalkOptions $options = null): FileList
src/Greph.php:50:    public static function searchText(string $pattern, string|array $paths, ?TextSearchOptions $options = null): array
src/Greph.php:81:    public static function buildTextIndex(
```

添加 `-i` 可进行不区分大小写的匹配，添加 `-w` 可进行全词匹配，添加 `-c` 可统计匹配项，添加 `-l` 可仅输出文件路径，添加 `-C 2` 可显示两行上下文，等等。完整列表请参见 [CLI参考](https://greph.inline0.dev/zh/docs/cli)。

## 你的第一次 AST 搜索

传入 `-p` 和符合 PHP 结构的模式，即可切换到结构化搜索：

```bash
vendor/bin/greph -p 'new $CLASS()' src
```

`$CLASS` 是一个元变量，可捕获任意类名。模式 `new $CLASS()` 会匹配所有不带参数的 `new` 表达式，无论类、格式或注释如何。使用 `new $CLASS($$$ARGS)` 可匹配带任意参数的调用。

每个 AST 匹配项都会输出文件、起始行和匹配的代码：

```text
src/Greph.php:43:new FileWalker()
src/Greph.php:52:new TextSearchOptions()
src/Greph.php:54:new TextSearcher()
```

其他实用模式：

```bash
# Any method call with any arguments
vendor/bin/greph -p '$obj->$method($$$ARGS)' src

# Any function declaration with a void return type
vendor/bin/greph -p 'function $name($$$PARAMS): void {}' src

# Old-style array calls
vendor/bin/greph -p 'array($$$ITEMS)' src
```

完整的模式语法请参见 [模式 / AST 搜索](https://greph.inline0.dev/zh/docs/modes/ast)。

## 你的第一次重写

添加 `-r`，即可将 AST 搜索转换为重写：

```bash
# Preview only
vendor/bin/greph -p 'array($$$ITEMS)' -r '[$$$ITEMS]' --dry-run src

# Apply
vendor/bin/greph -p 'array($$$ITEMS)' -r '[$$$ITEMS]' src

# Confirm each file before writing
vendor/bin/greph -p 'array($$$ITEMS)' -r '[$$$ITEMS]' --interactive src
```

在匹配项之外，重写会保留原有格式：只替换匹配节点，周围的空白、缩进和注释均保持不变。匹配节点本身会根据模板重新生成，因此其布局会规范化，节点内部的注释也可能丢失。详情请参见 [模式 / 重写](https://greph.inline0.dev/zh/docs/modes/rewrite)。

## PHP API

静态 `Greph\Greph` 门面提供了与 CLI 相同的操作：

```php
use Greph\Greph;
use Greph\Ast\AstSearchOptions;
use Greph\Text\TextSearchOptions;

$results = Greph::searchText(
    'function',
    'src',
    new TextSearchOptions(fixedString: true, caseInsensitive: true),
);

foreach ($results as $file) {
    foreach ($file->matches as $match) {
        echo "{$file->file}:{$match->line}:{$match->content}\n";
    }
}

$matches = Greph::searchAst(
    'new $CLASS()',
    'src',
    new AstSearchOptions(),
);

foreach ($matches as $match) {
    echo "{$match->file}:{$match->startLine}:{$match->code}\n";
}
```

完整功能范围见 [API](https://greph.inline0.dev/zh/docs/api)。

## 索引搜索

重复执行的工作负载可从预热索引中受益。构建一次，然后多次查询：

```bash
# Text index
vendor/bin/greph-index build .
vendor/bin/greph-index search -F "function" .

# AST fact index
vendor/bin/greph-index ast-index build .
vendor/bin/greph-index ast-index search 'new $CLASS()' src

# Cached parsed-tree index
vendor/bin/greph-index ast-cache build .
vendor/bin/greph-index ast-cache search 'array($$$ITEMS)' src
```

默认情况下，索引位于项目根目录下的 `.greph-index`、`.greph-ast-index` 和 `.greph-ast-cache` 中。

对于持续变化的目录树，请选择生命周期配置，而不要将所有预热索引一视同仁：

```bash
vendor/bin/greph-index build . --lifecycle static
vendor/bin/greph-index build . \
  --lifecycle opportunistic-refresh \
  --auto-refresh-max-files 32 \
  --auto-refresh-max-bytes 1048576
vendor/bin/greph-index stats . --dry-refresh
```

常见模式如下：

- 将稳定基线保留为 `static`
- 将持续变化的覆盖层保留为 `opportunistic-refresh`
- 使用 `stats --dry-refresh` 检查过期行为

### 多索引预热搜索

你可以在一条命令中搜索多个预热索引：

```bash
vendor/bin/greph-index search -F "apply_filters" . \
  --index-dir wordpress/.greph-index \
  --index-dir wp-content/plugins/my-plugin/.greph-index \
  --show-index-origin

vendor/bin/greph-index ast-index search 'new $CLASS()' . \
  --index-dir wordpress/.greph-ast-index \
  --index-dir wp-content/plugins/my-plugin/.greph-ast-index \
  --show-index-origin
```

### 命名索引集

如果你需要反复执行此操作，可将布局写入 `.greph-index-set.json`，然后使用集合子命令，而不必重复指定标志：

```bash
vendor/bin/greph-index set build
vendor/bin/greph-index set stats --dry-refresh
vendor/bin/greph-index set search --show-index-origin -F "apply_filters" .
vendor/bin/greph-index set search --mode ast-index 'new $CLASS()' .
vendor/bin/greph-index set search --mode ast-cache 'array($$$ITEMS)' .
```

### 规划器跟踪

若要查看预热搜索如何缩小候选范围，请添加 `--trace-plan`：

```bash
vendor/bin/greph-index search --trace-plan -F "function" .
vendor/bin/greph-index ast-index search --trace-plan 'new $CLASS()' .
```

完整的预热工作流请参见 [索引 / 文本](https://greph.inline0.dev/zh/docs/indexed/text) 和 [索引 / AST](https://greph.inline0.dev/zh/docs/indexed/ast)。

## 兼容性包装器

如果你已有会使用 ripgrep 或 ast-grep 的工具或代理，可直接使用这些包装器：

```bash
vendor/bin/rg --json -F "function" src
vendor/bin/sg --pattern 'new $CLASS()' src --lang php
```

两个包装器复用同一引擎，并已通过针对上游二进制文件的探测验证。经验证的功能范围记录在 [兼容性 / rg](https://greph.inline0.dev/zh/docs/compatibility/rg) 和 [兼容性 / sg](https://greph.inline0.dev/zh/docs/compatibility/sg) 中，并在生成的 [功能矩阵](https://greph.inline0.dev/zh/docs/advanced/feature-matrix) 中重现。

## 配置

Greph 会识别两种磁盘约定：

- `.gitignore`：默认遵循。传入 `--no-ignore` 可禁用。
- `.grephignore`：语法与 `.gitignore` 相同，并在其基础上应用。适合添加不想纳入版本控制的工具专用排除规则。

默认索引目录位于所选根目录下的 `.greph-index`、`.greph-ast-index` 和 `.greph-ast-cache`。可在任何 `greph-index` 子命令中使用 `--index-dir` 覆盖，或使用 `.greph-index-set.json` 设置可重复使用的多索引布局。
