Skip to main content

moai ast-grep / ast-edit 结构化搜索与替换

更新 2026-08-04 3 分钟阅读 在 GitHub 上编辑 ↗

moai ast-grep 以语法树为单位扫描代码,moai ast-edit 则实际替换匹配到的代码。与基于文本的 grep 不同,两者都按语法结构匹配,因此不受空格、换行和变量名差异的影响。

两个命令都调用 ast-grep CLI(sg),而未安装 sg 时二者的行为是刻意不同的。ast-grep 是常被接入 CI 作为门禁的检测命令,因此会把安装指引写到 stderr 并以非零码退出——从未运行的扫描不能视为“没有问题”。ast-edit 是替换命令,“没有可应用的改动"本身就是正常的空操作,所以只输出提示并以 0 退出。安装 sg 请参阅 ast-grep 快速开始moai doctor 也会报告它是否存在。

读取与写入是分离的命令。 ast-grep 绝不修改文件,ast-edit 会修改。由于是独立命令,授予 Bash(moai ast-grep:*) 不会同时打开写入权限。

moai ast-grep — 扫描(只读)

参数说明
--format输出格式:text(默认)、jsonsarif
--lang仅扫描指定语言(如 gopythontypescript
--severity显示的最低严重级别(errorwarninginfo
--rules-dir规则目录路径(默认 .moai/config/astgrep-rules
--dry仅输出将要应用的规则列表,跳过实际扫描
bash
# 扫描整个项目
moai ast-grep ./

# 仅 Go,输出 SARIF(用于上传至 GitHub code scanning)
moai ast-grep --format=sarif --lang=go ./internal/

# 仅显示 error 级别
moai ast-grep --severity=error ./

moai ast-edit — 替换(修改文件)

不带 --dry 运行会 直接修改文件。建议先用 --dry 预览变更内容。

参数说明
--dry不修改文件,仅输出将要变更的内容
--pattern要匹配的 ast-grep 模式(与 --rewrite 配合使用)
--rewrite替换后的模式(与 --pattern 配合使用)
--rule仅应用指定 ID 的规则(规则模式)
--lang目标代码的语言
--rules-dir规则目录路径(默认 .moai/config/astgrep-rules
--format输出格式:text(默认)、json

Pattern 模式

同时指定 --pattern--rewrite 会替换所有匹配的代码。仅指定其中一个会被拒绝并报错。

bash
# 先预览
moai ast-edit --dry --pattern 'foo($A)' --rewrite 'bar($A)' --lang go ./internal/

# 确认后实际应用
moai ast-edit --pattern 'foo($A)' --rewrite 'bar($A)' --lang go ./internal/

规则模式

不带 --pattern 运行时,命令会读取规则目录,仅应用声明了 fix: 字段的规则。没有 fix: 的规则属于仅检测类型,会被跳过并报告数量。

bash
# 应用所有 fix: 规则(预览)
moai ast-edit --dry ./internal/

# 仅应用特定规则
moai ast-edit --rule my-rule-id ./internal/

随附的规则集(go/hardcodingsecurity/credentialssecurity/cryptosecurity/injection)全部为 仅检测。自动替换可能改变语义或破坏编译,因此有意未添加 fix:。如需自动替换,请在项目自有规则中声明 fix:

规则文件位置

两个命令默认都读取 .moai/config/astgrep-rules/sgconfig.yml 定义生效的规则目录。

相关文档