# `Grep` 工具

一个强大的**内容搜索**工具，构建在 [ripgrep](https://github.com/BurntSushi/ripgrep)
(`rg`) 之上。它回答这个问题：*"哪些文件包含匹配此模式的文本，以及匹配的行是什么？"*

Grep 搜索文件**内部**。（它的兄弟工具 `Glob` 搜索文件**名称**。见
`glob-tool.md`。）

---

## 何时使用

- 查找函数、变量、类或字符串的定义或使用位置。
- 在代码库中定位某个模式的所有出现。
- 统计某事出现的次数。
- 任何时候你想在 shell 中使用 `grep`、`rg`、`egrep` 或 `grep -r`。

> **重要提示：** 始终优先使用此工具，而非通过 Bash 工具运行 `grep`/`rg`。
> 它是专门为此构建的，默认遵循 `.gitignore`，并以干净、结构化的形式返回结果。
> 不鼓励在 Bash 中运行 `grep`。

---

## 参数

| 参数      | 类型    | 必需 | 描述                                                                                         |
| -------------- | ------- | -------- | --------------------------------------------------------------------------------------------------- |
| `pattern`      | string  | **是**  | 要搜索的正则表达式。支持完整的正则语法（例如 `log.*Error`、`function\s+\w+`）。 |
| `path`         | string  | 否       | 要搜索的文件或目录。默认为当前工作目录。                          |
| `glob`         | string  | 否       | 用于筛选要搜索文件的 Glob 模式（例如 `*.js`、`*.{ts,tsx}`）。映射到 ripgrep 的 `--glob`。 |
| `type`         | string  | 否       | 要搜索的文件类型（例如 `js`、`py`、`rust`、`go`）。对于标准类型，通常比 `glob` 更高效。 |
| `output_mode`  | string  | 否       | 以下之一：`content`、`files_with_matches`（默认）或 `count`。控制返回内容（见下文）。 |
| `-i`           | boolean | 否       | 不区分大小写搜索。                                                                            |
| `-n`           | boolean | 否       | 显示行号。仅当 `output_mode` 为 `content` 时适用。                                    |
| `-A`           | number  | 否       | 每个匹配**之后**显示的上下文行数。（仅 `content` 模式。）                               |
| `-B`           | number  | 否       | 每个匹配**之前**显示的上下文行数。（仅 `content` 模式。）                              |
| `-C`           | number  | 否       | 每个匹配前后显示的上下文行数。（仅 `content` 模式。）                    |
| `multiline`    | boolean | 否       | 启用多行模式，使 `.` 匹配换行符，模式可以跨行。默认 `false`。         |
| `head_limit`   | number  | 否       | 将输出限制为前 N 行/条目（就像管道到 `head -N`）。适用于所有输出模式。 |

---

## 输出模式说明

`output_mode` 参数改变了你获取的*内容*。选择正确的一个可以保持结果聚焦：

- **`files_with_matches`** *（默认）* — 仅返回包含至少一个匹配的文件路径列表。最适合只需要知道*在哪里*的时候。最廉价的输出。

- **`content`** — 返回实际的匹配行（以及通过 `-A`/`-B`/`-C` 获取的可选周围上下文）。此模式支持 `-n`、`-A`、`-B` 和 `-C`。当你需要*阅读*匹配内容而不仅仅是定位文件时使用。

- **`count`** — 返回每个文件的匹配数量。用于在深入之前评估某个模式有多普遍。

---

## 正则表达式说明

- `pattern` 是一个正则表达式，**不是**字面字符串。像 `.`、`(`、`)`、`{`、`[`、`*`、`+`、`?`、`|`、`\` 这些字符具有特殊含义。
- 要字面匹配它们，使用反斜杠转义。示例：要在 Go 中查找字面文本 `interface{}`，将模式写为 `interface\{\}`。
- Ripgrep 使用 Rust 正则引擎。默认情况下，模式按**行**匹配——模式不能跨多行，除非设置 `multiline: true`。

---

## 示例

**查找每个提到 `TODO` 的文件（仅文件列表）：**
```json
{ "pattern": "TODO" }
```

**显示匹配行和行号，仅限 JavaScript 文件：**
```json
{
  "pattern": "useState",
  "glob": "*.js",
  "output_mode": "content",
  "-n": true
}
```

**不区分大小写搜索，带 3 行周围上下文：**
```json
{
  "pattern": "deprecated",
  "output_mode": "content",
  "-i": true,
  "-C": 3
}
```

**统计 `console.log` 在每个 TypeScript 源文件中的出现次数：**
```json
{
  "pattern": "console\\.log",
  "type": "ts",
  "output_mode": "count"
}
```

**多行搜索——跨越数行的 `struct` 块：**
```json
{
  "pattern": "struct \\{[\\s\\S]*?name",
  "multiline": true,
  "output_mode": "content"
}
```

---

## 技巧和注意事项

- **尽早筛选。** 将 `pattern` 与 `glob` 或 `type` 组合比搜索所有内容后筛选噪音更快、更干净。
- **`type` 对比 `glob`。** `type` 使用 ripgrep 的内置语言定义（它知道哪些扩展名属于 `python`、`rust` 等）。`glob` 给你对文件模式的精确控制。使用哪一个来表达你的意图更清楚。
- **在 JSON 中转义。** 因为模式通过 JSON 传输，正则中的反斜杠必须在 JSON 字符串中写为 `\\`（例如 `\\.` 匹配字面点号）。
- **`.gitignore` 感知。** 像 ripgrep 一样，该工具默认跳过忽略的文件（例如 `node_modules`）——通常正是你想要的。
- **探索时与 `Glob` 配对。** 使用 `Glob` 按名称发现候选文件，然后使用 `Grep` 搜索其内容——或者将两者交给一个代理进行广泛的展开搜索。
