跳转到正文

快速入门

安装

通过 Composer 安装 Greph:

命令行
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 自动加载器,因此至少需要该版本:

命令行
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),因此当其他扩展缺失时,Composer 不会发出警告。

可选:

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

搜索、重写和索引操作都不会调用 proc_open() 或 shell_exec();只有并行扫描会派生进程,若没有 pcntl_fork(),则会回退到单进程。有关禁用 proc_open()、shell_exec() 或 pcntl_fork() 的主机,请参见 进程受限的主机。

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

命令行
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参考。

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

命令行
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()

其他实用模式:

命令行
# 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 搜索。

你的第一次重写

添加 -r,即可将 AST 搜索转换为重写:

命令行
# 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

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

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。

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

命令行
# 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 中。

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

命令行
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 检查过期行为

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

命令行
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,然后使用集合子命令,而不必重复指定标志:

命令行
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:

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

完整的预热工作流请参见 索引 / 文本 和 索引 / AST。

兼容性包装器

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

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

两个包装器复用同一引擎,并已通过针对上游二进制文件的探测验证。经验证的功能范围记录在 兼容性 / rg 和 兼容性 / sg 中,并在生成的 功能矩阵 中重现。

配置

Greph 会识别两种磁盘约定:

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

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