ripgrep 用户指南深度实战:从逐行正则搜索到忽略过滤、类型过滤、替换与二进制文件处理
本文基于 ripgrep 官方用户指南 GUIDE.md 逐章展开,覆盖 ripgrep 的核心工作流:逐行模式匹配与正则语法、递归目录搜索、自动/手动过滤、输出替换、配置文件、文件编码、二进制文件三态处理以及 --pre 预处理器机制。读完本文后,你不仅能完整掌握 ripgrep 的常用参数与操作手法,还能对照 crates/core/search.rs、crates/core/flags/config.rs、crates/ignore/src/types.rs 等源码位置,理解每个行为背后的实现依据。
基础:逐行匹配与正则模式
ripgrep 是一个命令行搜索工具:它假定自己逐行读取文件,若某一行匹配你给定的模式就打印该行,不匹配则跳过。这是理解 ripgrep 一切输出格式(行号、文件分组、颜色高亮)的前提。
指南以搜索 ripgrep 自身源码为例。在 README.md 中查找字面词 fast:
$ rg fast README.md
75: faster than both. (N.B. It is not, strictly speaking, a "drop-in" replacement
88: color and full Unicode support. Unlike GNU grep, `ripgrep` stays fast while
119:### Is it really faster than everything else?
124:Summarizing, `ripgrep` is fast because:
129: optimizations to make searching very fast.
这里 fast 是一个"字面量"(literal)模式,ripgrep 对每一行做包含判断,并默认附上行号;若终端支持颜色,命中部分会被高亮。
ripgrep 同时支持完整的正则表达式。想找到"fast 后面还跟着若干字母"的行:
$ rg 'fast\w+' README.md
75: faster than both. (N.B. It is not, strictly speaking, a "drop-in" replacement
119:### Is it really faster than everything else?
模式 fast\w+ 表示 fast 后跟一个或多个词字符(\w 匹配 a、L 这类构词字符,不匹配 .、空格;+ 表示"前一模式重复一次或多次")。因此裸词 fast 不匹配,faster、faste 都匹配。若改用 fast\w*(* 表示零次或多次),匹配到的行与 fast 相同,但颜色高亮范围会覆盖整个 faster 而不仅是 fast 前缀:
$ rg 'fast\w*' README.md
75: faster than both. (N.B. It is not, strictly speaking, a "drop-in" replacement
88: color and full Unicode support. Unlike GNU grep, `ripgrep` stays fast while
119:### Is it really faster than everything else?
124:Summarizing, `ripgrep` is fast because:
129: optimizations to make searching very fast.
指南明确说明不提供完整的正则教程,ripgrep 所用的正则方言以 regex 文档为准(其 crate 位于 crates/regex/,正则配置入口见 crates/regex/src/config.rs)。
排查技巧:如果 ripgrep 提示"没有搜索任何文件",用 --debug 重新运行。指南指出的一个常见原因是 $HOME/.gitignore 中存在 * 规则——这与下文"自动过滤"机制直接相关。
递归搜索:ripgrep 的默认运行模式
指南第一个例子搜索单个文件,但 ripgrep 的默认模式是递归搜索当前工作目录,因此这几乎不需要额外参数。在解压后的 ripgrep 源码树中查找所有名为 write 的函数定义:
$ rg 'fn write\('
src/printer.rs
469: fn write(&mut self, buf: &[u8]) {
termcolor/src/lib.rs
227: fn write(&mut self, b: &[u8]) -> io::Result<usize> {
250: fn write(&mut self, b: &[u8]) -> io::Result<usize> {
428: fn write(&mut self, b: &[u8]) -> io::Result<usize> { self.wtr.write(b) }
...
要点:
- 未给出路径时,
rg foo等价于rg foo ./; (在正则中有特殊含义所以需要转义为\(,也可以直接用-F把模式当字面量:rg -F 'fn write(';- 结果按文件分组打印(先文件名后行),跨了
src与依赖库termcolor两个目录; - 想限定范围,直接给出目录:
rg 'fn write\(' src,或cd进目标目录后再搜索。
在当前仓库中,目录遍历逻辑位于 crates/ignore/src/walk.rs,它决定了哪些文件会进入搜索管线。
自动过滤:ripgrep 最关键的"不搜什么"
指南强调,递归搜索之后,ripgrep 最重要的特性是它默认不搜索什么。搜索目录时,默认忽略:
- 命中以下三类 glob 规则的文件与目录(按优先级从低到高):
.gitignore规则(包括全局与仓库级规则;也包括属于同一 git 仓库的父目录中的.gitignore,除非给出--no-require-git);.ignore规则,与 gitignore 规则冲突时优先生效(同样包含父目录中的.ignore);.rgignore规则,与.ignore冲突时优先生效(同样包含父目录中的.rgignore);
- 隐藏文件和目录;
- 二进制文件(ripgrep 把含
NUL字节的文件视为二进制); - 符号链接默认不跟随。
对应的开关:
| 行为 | 标志 | 短写 |
|---|---|---|
| 关闭全部忽略过滤 | --no-ignore |
— |
| 搜索隐藏文件/目录 | --hidden |
-. |
| 把二进制当文本搜索 | --text |
-a(注意:二进制可能向终端喷出控制字符) |
| 跟随符号链接 | --follow |
-L |
指南还提供了一个递进式排障标志 --unrestricted(-u):
-u:关闭.gitignore处理;-uu:进而搜索隐藏文件与目录;-uuu:进而搜索二进制文件。
当你不确定是过滤规则藏起了结果时,多加几个 -u 是最快的确认手段;仍无法解释时再用 --debug。
gitignore 处理的完整范围:除了各级 .gitignore,ripgrep 还尊重仓库专属规则 $GIT_DIR/info/exclude,以及 core.excludesFile(在 Unix 类系统上通常是 $XDG_CONFIG_HOME/git/ignore)中的全局忽略规则。这些规则的收集逻辑见 crates/ignore/src/gitignore.rs。
用 .ignore 覆写 .gitignore:假设某目录有如下 .gitignore:
log/
log 目录不被 git 跟踪。但你可能希望搜索它的输出,又不想让它进 git。在同一目录创建 .ignore:
!log/
由于 .ignore 优先级高于 .gitignore(.rgignore 又高于 .ignore),ripgrep 会先看到白名单规则 !log/ 并搜索该目录。与 .gitignore 相同,.ignore 可以放在任意目录,规则相对于所在目录生效。
补充两个细节:
--ignore-file-case-insensitive让.gitignore/.ignore规则按大小写不敏感方式匹配,适合 Windows、macOS 这类大小写不敏感的文件系统;代价是明显的性能损耗,因此默认关闭;- glob 语义的权威解释参考
man gitignore。
手动过滤一:glob 模式
自动过滤依赖环境(既有的 .gitignore),而 glob 过滤是临时的、显式的。仍以上述源码树为例,想看谁依赖参数解析器 lexopt:
$ rg lexopt
[大量结果]
$ rg lexopt -g '*.toml'
Cargo.toml
57:lexopt = "0.3.0"
-g '*.toml' 的含义是"被搜索的每个文件都必须匹配这个 glob"。注意 '*.toml' 要用单引号,防止 shell 展开 *。
glob 同样支持 ! 取反:
$ rg lexopt -g '!*.toml'
[大量结果,但都不以 .toml 结尾]
! 表示黑名单这一点"有点非标准",但作者有意与 .gitignore 的写法保持一致——只是语义方向相反:.gitignore 中 ! 前缀表示白名单,命令行上 ! 表示黑名单。
顺序即优先级:glob 的解释方式与 .gitignore 相同,后面的规则覆盖前面的:
$ rg lexopt -g '!*.toml' -g '*.toml' # 只搜 *.toml
反过来:
$ rg lexopt -g '*.toml' -g '!*.toml' # 什么都不匹配
因为只要存在至少一个非黑名单 glob,就要求每个被搜索文件至少匹配一个 glob;此时黑名单规则压过前面的 glob,导致任何文件都无法被搜索。
手动过滤二:文件类型
当你反复使用同一组 glob(比如总是只想看 Rust 文件),可以直接用文件类型替代 glob:
$ rg 'fn run' -g '*.rs'
# 等价于
$ rg 'fn run' --type rust
# 更简洁
$ rg 'fn run' -trust
--type 的本质是"给一组 glob 起一个名字",一个类型可以覆盖多种扩展名。以 C 语言为例,用 glob 需要写 -g '*.{c,h}',用类型只需 -tc:
$ rg 'int main' -g '*.{c,h}'
$ rg 'int main' -tc
黑名单文件类型同理:
$ rg lexopt --type-not rust
$ rg lexopt -Trust # -T = --type-not
即 -t 是"包含该类型",-T 是"排除该类型"。
查看某类型由哪些 glob 构成:
$ rg --type-list | rg '^make:'
make: *.mak, *.mk, GNUmakefile, Gnumakefile, Makefile, gnumakefile, makefile
内置类型覆盖常见的公开格式(定义集中在 crates/ignore/src/default_types.rs),你也可以自定义。例如把"web"文件定义为 HTML/CSS/JS:
$ rg --type-add 'web:*.html' --type-add 'web:*.css' --type-add 'web:*.js' -tweb title
# 或更简洁
$ rg --type-add 'web:*.{html,css,js}' -tweb title
再次 rg --type-add 'web:*.{html,css,js}' --type-list 时,web 会出现在列表中,尽管它不是内置类型。
重要:--type-add 只对当前命令生效,不会被持久化。要全局可用,要么建 shell 别名:
alias rg="rg --type-add 'web:*.{html,css,js}'"
要么把 --type-add=web:*.{html,css,js} 写进 ripgrep 配置文件(见下文"配置文件"一节)。
从源码看,类型名还受到严格约束:crates/ignore/src/types.rs 中 TypesBuilder::add 要求类型名只能是字母数字且不能占用 all,add_def(L442-L479)还额外支持 {name}:include:{已有类型列表} 的复合定义形式,即一个类型可以由若干已有类型组合而成——这一点指南没有展开,属于源码层面的加分能力。
特殊的 all 类型
--type all 表示选择 --type-list 中列出的所有支持类型(包括命令行 --type-add 添加的)。等价于为每个内置类型各写一个 --type 标志。
指南给了一个很好的边界例子:当前目录有 my-shell-script(无扩展名脚本)和 my-shell-library.bash:
rg --type sh与rg --type all都只命中my-shell-library.bash,因为sh类型的 glob 不匹配无扩展名文件;- 反过来
rg --type-not all会搜索my-shell-script但不搜my-shell-library.bash。
源码中 all 的特殊处理见 crates/ignore/src/types.rs#L381-L404:select/negate 遇到名字 all 时,会遍历当前已定义的全部类型逐个添加选择/反选择。
替换:--replace 只改输出,不改文件
ripgrep 提供有限的输出改写能力。仍以 rg fast README.md 为例,把命中片段替换为 FAST:
$ rg fast README.md --replace FAST
75: FASTer than both. (N.B. It is not, strictly speaking, a "drop-in" replacement
88: color and full Unicode support. Unlike GNU grep, `ripgrep` stays FAST while
119:### Is it really FASTer than everything else?
124:Summarizing, `ripgrep` is FAST because:
129: optimizations to make searching very FAST.
# 或简写
$ rg fast README.md -r FAST
--replace 只作用于匹配到的那部分文本。想替换整行,需要让模式覆盖整行:
$ rg '^.*fast.*$' README.md -r FAST
75:FAST
88:FAST
119:FAST
124:FAST
129:FAST
或者组合 --only-matching(-o)与 --replace:
$ rg fast README.md --only-matching --replace FAST
75:FAST
88:FAST
119:FAST
124:FAST
129:FAST
# 简写
$ rg fast README.md -or FAST
捕获组可以直接写进替换串。找 fast 后面跟的另一个词并连字符拼接:
$ rg 'fast\s+(\w+)' README.md -r 'fast-$1'
88: color and full Unicode support. Unlike GNU grep, `ripgrep` stays fast-while
124:Summarizing, `ripgrep` is fast-because:
替换串 fast-$1 由字面 fast- 加第 1 号捕获组内容组成。捕获组从 0 开始编号,但第 0 组恒为整个匹配,第 1 组才是模式中第一个显式括号组。也可以用命名组,下面的命令与上例等价:
$ rg 'fast\s+(?P<word>\w+)' README.md -r 'fast-$word'
88: color and full Unicode support. Unlike GNU grep, `ripgrep` stays fast-while
124:Summarizing, `ripgrep` is fast-because:
替换串中捕获组的展开实现位于 crates/matcher/src/interpolate.rs。
必须牢记:ripgrep 从不修改你的文件,--replace 只控制输出,仓库中也没有任何"就地替换"标志。
配置文件:RIPGREP_CONFIG_PATH 与 rc 文件格式
默认参数并不总合适,而 shell 别名也不总是方便,因此 ripgrep 支持配置文件。它不会自动去任何目录找配置文件,必须显式设置环境变量:
export RIPGREP_CONFIG_PATH=$HOME/.ripgreprc
配置文件只有两条格式规则:
- 每行去掉首尾空白后作为一个 shell 参数;
- 以
#开头的行(前面可带任意空白)被忽略。
没有转义机制——每行按原样作为一个命令行参数交给 ripgrep。
一份示例配置(展示了格式的种种特性):
$ cat $HOME/.ripgreprc
# 不让 ripgrep 把超长行喷满终端,并显示预览
--max-columns=150
--max-columns-preview
# 添加我的 'web' 类型
--type-add
web:*.{html,css,js}*
# 默认搜索隐藏文件/目录
--hidden
# 用 glob 模式包含/排除文件或目录
--glob=!.git/*
# 或
--glob
!.git/*
# 设置颜色
--colors=line:none
--colors=line:style:bold
# 大小写谁在乎!
--smart-case
带值的标志有两种等价写法:同一条 = 分隔(--max-columns=150),或标志与值分两行写。原因是 ripgrep 的参数解析器认识 --max-columns=150 这种"带值单参数",而写 --max-columns 150 两词时它无法确定关系。分两行完全等价,只是风格问题。注释鼓励常写,空行随意。
覆盖机制:假如你在用上面的配置,临时想看超过 150 列的长行,只需在命令行传 --max-columns 0(或 -M0)覆盖即可。原理是:配置文件参数被前插(prepended)到显式命令行参数之前,而后出现的标志覆盖先出现的标志,因此行为符合直觉。各标志的文档会说明它会被哪些标志覆盖。
两个实用收尾:
- 不确定 ripgrep 正在读哪个配置文件时,加
--debug,调试输出会标注加载的配置及其读到的参数; - 想绝对确认没有读取任何环境配置,传
--no-config,无论未来 ripgrep 增加多少种配置方式,它都保证只信命令行。
源码印证:crates/core/flags/config.rs 中 args() 首先读取 RIPGREP_CONFIG_PATH,未设置时直接返回空参数并记录调试日志;parse_reader(L84-L108)逐行 trim 后跳过空行与 # 行,每行转为 OsString 原样保留——这正对应文档描述的"无转义、每行一个参数"。文件内的单元测试还验证了 Unix 下可容忍非 UTF-8 字节、而 Windows 下会按行报错的平台差异。
文件编码:--encoding auto 的默认行为
编码本身是复杂话题,指南将其对 ripgrep 的要点归纳为:
- 文件只是一堆字节,无法可靠地判断其编码;
- 要么模式与文件编码一致,要么必须对模式或文件做转码;
- ripgrep 在纯文本上表现最好,最常见的编码是 ASCII、latin1、UTF-8;特例是 Windows 环境中普遍存在的 UTF-16。
默认即 --encoding auto,其行为:
- 假设所有输入 ASCII 兼容(凡是落在 ASCII 码点范围内的字节,其值就是该 ASCII 码点),这覆盖 ASCII、latin1、UTF-8;
- ripgrep 对 UTF-8 支持最好:正则引擎支持 Unicode 特性,
\w按 Unicode 定义匹配所有词字符,.匹配任意 Unicode 码点而非任意字节。这些构造都假定 UTF-8——遇到文件里的非 UTF-8 字节时,它们根本不会匹配; - 对 UTF-16,ripgrep 默认做"BOM 嗅探":读取文件前三字节,若是 UTF-16 BOM,则把文件内容从 UTF-16 转码为 UTF-8 再搜索(转码带来额外性能开销);遇到无效 UTF-16 时用 Unicode 替换码点顶替无效码元;
- 其他编码用
-E/--encoding指定(取值来自 Encoding Standard),ripgrep 假定所有被搜索文件(除非文件自带 BOM)都是该编码,并执行与 UTF-16 情况相同的转码步骤。
默认情况下 ripgrep 不要求输入是合法 UTF-8,它可以直接搜索任意字节。搜索非 UTF-8 内容时模式的有效性会下降;若文件字节不 ASCII 兼容,模式很可能什么都找不到。但这一模式很重要——它让你在"大体是二进制/乱码"的文件中找出其中的 ASCII 或 UTF-8 片段。
-E none 是特殊值:完全禁用一切编码逻辑(包括 BOM 嗅探),直接搜索文件原始字节、零转码。例如搜索字符串 Шерлок 的原始 UTF-16 编码:
$ rg '(?-u)\(\x045\x04@\x04;\x04>\x04:\x04' -E none -a some-utf16-file
当然,通常你不需要这么干,直接写原文即可:
$ rg 'Шерлок' some-utf16-file
最后在正则内部关闭 Unicode:若想让 . 匹配任意字节而非任意 Unicode 码点(比如搜二进制文件时,因为默认的 . 不匹配无效 UTF-8):
$ rg '(?-u:.)'
该开关作用于模式任意部分。下面这个例子找"一个 Unicode 词字符 + 一个 ASCII 词字符 + 一个 Unicode 词字符":
$ rg '\w(?-u:\w)\w'
二进制数据:三种模式的 NUL 启发式
除了隐藏文件与 .gitignore 规则,ripgrep 还默认跳过二进制文件——PDF、图片之类通常不是正则搜索目标,而且命中二进制内容时把二进制数据喷进终端可能引发各种怪事。
与"跳过隐藏文件"不同,二进制没有可靠判定法。权衡正确性与性能后,ripgrep 采用最简单有效的启发式:文件中只要含一个 NUL 字节就判定为二进制。麻烦在于大多数二进制文件只是"开头附近"就有 NUL,并非必然——NUL 也可能是大文件的最后一个字节,该文件仍算二进制。这给实现带来复杂度,也造成一些反直觉的用户体验。
宏观上 ripgrep 对二进制文件有三种模式:
- 默认模式:尽量把二进制文件从搜索中彻底移除,模仿自动过滤的语义——一旦发现是二进制就停止搜索。若在此之前已经打印过命中(因为
NUL出现得很晚),会打印一条"搜索提前终止"的警告。该模式只作用于目录递归遍历发现的文件:显式给出的路径不受此约束,例如rg foo .file会搜隐藏的.file,rg foo binary-file也会自动以"二进制模式"搜索binary-file。 - 二进制模式(
--binary强制开启):与默认模式相似,但看到NUL后不总是立即停。它会继续搜到满足以下二者之一为止:文件末尾,或发现了一个匹配。因此该模式下"报告无匹配"意味着文件里确实没有匹配;命中时会打印类似默认模式的"提前终止"提示。目的是既能发现所有文件中的匹配,又不让二进制数据倒进终端。 - 文本模式(
-a/--text):彻底禁用二进制检测,所有文件都当文本搜。适合"大体是文本但含NUL"的文件,或你就是想搜二进制数据。注意对超大二进制文件使用此模式时,ripgrep 可能占用大量内存。
还有一层实现细节会影响判定结果——检测范围取决于搜索策略:
- 使用内存映射(mmap)时,只在文件开头若干 KB 及每个命中行上做二进制检测;
- 不使用 mmap 时,对所有被搜索字节做检测。
也就是说,同一文件是否被判为二进制可能因内部策略不同而变化。想保持判定一致,可用 --no-mmap 关闭内存映射(代价是在某些平台上搜索超大文件时轻微变慢)。
源码层面,检测策略枚举在 crates/searcher/src/line_buffer.rs 的 BinaryDetection(None/Quit(byte)/Convert(byte) 三态),crates/core/search.rs 中每次搜索前都会按配置 set_binary_detection,随后在 search_reader/search_path 中执行。
预处理器:--pre 让 ripgrep 会搜任何可转成文本的格式
在 ripgrep 中,预处理器(preprocessor)是一个外部命令,ripgrep 在搜索每个文件之前先用它转换输入。这让 ripgrep 无需"学会"某种格式,就能搜索任何能被自动转成文本的内容。
典型例子是搜 PDF。PDF 是二进制格式,页面上的文字未必是连续 UTF-8,所以即使加 -a/--text 也搜不到:
$ rg 'The Commentz-Walter algorithm' 1995-watson.pdf
$
可以先手动转文本再搜:
$ pdftotext 1995-watson.pdf > 1995-watson.txt
$ rg 'The Commentz-Walter algorithm' 1995-watson.txt
316:The Commentz-Walter algorithms : : : : : : : : : : : : : : :
7165:4.4 The Commentz-Walter algorithms
10062:in input string S , we obtain the Boyer-Moore algorithm. The Commentz-Walter algorithm
...
(pdftotext 属于 poppler 库。)但目录里全是 PDF 时手动转换太痛苦,这时用 --pre。--pre 接收一个命令名,对每个被搜索文件执行它:ripgrep 把文件路径作为唯一参数传给命令,同时把文件内容送入 stdin。据此写一个包装脚本:
$ cat preprocess
#!/bin/sh
exec pdftotext - -
把 preprocess 与 1995-watson.pdf 放在同目录后即可:
$ rg --pre ./preprocess 'The Commentz-Walter algorithm' 1995-watson.pdf
316:The Commentz-Walter algorithms : : : : : : : : : : : : : : :
7165:4.4 The Commentz-Walter algorithms
10062:in input string S , we obtain the Boyer-Moore algorithm. The Commentz-Walter algorithm
...
注意 preprocess 必须能解析为 ripgrep 可读的命令:最简做法是放进 PATH(或等效机制)里,或使用绝对路径。指南还给出对比数据:同一 PDF 上,rg --pre ./preprocess ... -c 耗时 0.697 秒,而 pdfgrep ... -c 耗时 1.336 秒;如果批量搜 PDF,ripgrep 的并行能力会进一步放大差距。
源码印证这一接口契约:crates/core/search.rs 的 search_preprocessor 中,cmd.arg(path) 传入路径、stdin(Stdio::from(File::open(path)?)) 把文件内容送入 stdin,与文档描述完全一致;should_preprocess(L284-L292)则说明:设置了预处理器但未给 glob 时,每个文件都会走预处理器。
更健壮的预处理器
上面的脚本对非 PDF 文件会失败:
$ echo foo > not-a-pdf
$ rg --pre ./preprocess 'The Commentz-Walter algorithm' not-a-pdf
not-a-pdf: preprocessor command failed: '"./preprocess" "not-a-pdf"':
-------------------------------------------------------------------------------
Syntax Warning: May not be a PDF file (continuing anyway)
Syntax Error: Couldn't find trailer dictionary
...
修复方法:只在"认为输入是非空 PDF"时才跑 pdftotext:
#!/bin/sh
case "$1" in
*.pdf)
# -s 保证文件非空
if [ -s "$1" ]; then
exec pdftotext - -
else
exec cat
fi
;;
*)
exec cat
;;
esac
还可以扩展到其他格式:文件名不能确定类型时,用 file 工具按内容嗅探:
#!/bin/sh
case "$1" in
*.pdf)
if [ -s "$1" ]; then
exec pdftotext - -
else
exec cat
fi
;;
*)
case $(file "$1") in
*Zstandard*)
exec pzstd -cdq
;;
*)
exec cat
;;
esac
;;
esac
降低预处理器开销
每个文件都启动一次预处理器进程,开销不小。若只有少数文件需要预处理,可用 --pre-glob 限定只对匹配 glob 的路径启用:
$ time rg --pre pre-rg 'fn is_empty' -c
crates/globset/src/lib.rs:1
crates/matcher/src/lib.rs:2
crates/ignore/src/overrides.rs:1
crates/ignore/src/gitignore.rs:1
crates/ignore/src/types.rs:1
real 0.138
$ time rg --pre pre-rg --pre-glob '*.pdf' 'fn is_empty' -c
crates/globset/src/lib.rs:1
crates/ignore/src/types.rs:1
crates/ignore/src/gitignore.rs:1
crates/ignore/src/overrides.rs:1
crates/matcher/src/lib.rs:2
real 0.008
同样搜索 ripgrep 仓库,加 --pre-glob '*.pdf' 后从 0.138 秒降到 0.008 秒——因为几乎所有文件都不需要再启动预处理器子进程。--pre-glob 的匹配逻辑即前文源码中的 preprocessor_globs(ignore::overrides::Override)。
常用选项速查
ripgrep 的标志多到记不住,指南选取了日常使用频率最高的一组:
-h:简版帮助;--help:完整版帮助(接近 man page 内容,建议管道进分页器);-i/--ignore-case:忽略大小写,rg -i fast同时匹配fast、fASt、FAST;-S/--smart-case:类似--ignore-case,但模式含大写字母时自动关闭忽略大小写。通常放进别名或配置文件;-F/--fixed-strings:关闭正则,模式按字面量处理;-w/--word-regexp:要求命中两侧都是词边界。相当于把模式包成\b{start-half}(?:pattern)\b{end-half}。注意这些"半边界"不要求一侧是词字符:rg -w -e -2能匹配(-2)中的-2,而rg '\b-2\b'不能;-c/--count:只报告命中行数总和;--files:打印 ripgrep 将要 搜索的文件但不实际搜索——排查过滤问题的利器;-a/--text:把二进制当纯文本搜索;-U/--multiline:允许匹配跨多行;-z/--search-zip:搜索压缩文件(gzip、bzip2、lzma、xz、lz4、brotli、zstd),默认关闭;-C/--context:显示命中周围的上下文行;--sort path:按文件名排序输出(会关闭并行,可能更慢);-L/--follow:递归搜索时跟随符号链接;-M/--max-columns:限制打印行长度;--debug:打印调试输出,用于理解某个文件为何被忽略、以及 ripgrep 从环境加载了什么配置。
小结
ripgrep 的使用心法可以浓缩为三层:逐行正则匹配是基础(含 ?P<name> 命名组、(?-u:...) 按片段关闭 Unicode 等正则细节);过滤决定搜什么(.gitignore/.ignore/.rgignore 优先级链、-g glob、-t/-T 类型与特殊的 all);模式与接口处理特殊输入(--encoding/BOM 嗅探、NUL 三态二进制检测、--pre/--pre-glob 预处理器、--replace 只改输出)。遇到问题时,-u 阶梯与 --debug 是排障的第一选择,RIPGREP_CONFIG_PATH 配置文件 + --no-config 则是参数长期化管理的开关。以上每个行为在当前仓库中都能找到对应的实现位置:忽略规则收集在 crates/ignore/,二进制检测与搜索策略在 crates/searcher/,预处理器与压缩解包在 crates/core/search.rs,配置文件解析在 crates/core/flags/config.rs。
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust0622
Hy4-previewHy4 preview 是由腾讯混元团队研发的新一代混合专家(MoE)旗舰模型。模型总参数量 770B,每个 token 激活 49B,主干共包含78层,第一层采用标准 FFN,其余 77 层均为 MoE 结构,每层包含 256 个路由专家与 1 个共享专家,每个 token 激活 top-8 路由专家及共享专家。主干之外原生内置 1 层 MTP(总参数量 10B,激活 0.7B)以支持投机解码。Python00
GLM-5.3GLM-5.3 与 GLM-5.2 使用相同的基座模型——所有提升均来自后训练。与 GLM-5.2 相比,它在复杂编程和长程任务上的表现显著提升。Jinja00
GLM-5.3-FlashGLM-5.3-Flash (320B-A18B),是GLM-5系列的首个原生多模态模型。320B总参数,能力超过GLM-5.2Jinja00
Spark-X2.5-4BSpark-X2.5-4B 旨在让强大的 AI 更实用、更高效、更易获得。在广泛日常任务中表现强劲,涵盖对话、写作、翻译、推理、编码、工具调用以及智能体工作流,并在同等规模的开源模型中取得领先成绩。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00