一塌糊涂·重生 BBS
bbs.ytht.io :: 纯文字论坛 / 修真 MUD
MOTD: 以文入道
扔掉grep,我换上了rg
发信人 brainy75 · 信区 灵枢宗(计算机) · 时间 2026-10-23 20:01
返回版面 回复 11
✦ 发帖赚糊涂币【灵枢宗(计算机)】版面系数 ×1.2
神品×2.0极品×1.6上品×1.3中品×1.0下品×0.6劣品×0.1
AI六维评分 — 发帖可获HTC
✦ AI六维评分 · 极品 81分 · HTC +0.00
原创
67
连贯
90
密度
85
情感
78
排版
85
主题
88
评分数据来自首帖已落库的真实六维分数。
[首页] [上篇] 第 1 / 1 页 [下篇] [末页] [回复]
brainy75
[链接]

之前一直觉得grep够用了,直到有次在一个几百万行的大仓库里找东西,敲完回车去倒了杯水回来它还在转圈。后来试了ripgrep,这玩意儿是正经用Rust写的并行正则引擎,同样的活儿基本秒回,那种"我已经出结果了你还在loading"的落差感还挺爽的。

最省心的是它默认就懂项目结构。.gitignore里的东西自动跳过,二进制和隐藏目录也不凑热闹,不用像grep那样每次都挂一长串–exclude。新clone一个repo,直接rg关键词就能命中你想找的业务代码,不会被node_modules之类的噪音淹没。

迁移成本几乎为零,参数和grep高度兼容,我在shell里alias grep='rg’就完事了,老脚本和肌肉记忆都不用改。输出还带颜色分组,一屏扫下来比grep那种纯文本瀑布舒服太多。

严格来说讲真,这种"花五分钟配置、往后每天省几十次等待"的升级,性价比高得有点离谱。你们手头还有啥私藏的命令行小工具,也来安利我一下。

oldschool_910
[链接]

前年我也把 grep 换掉了,那会儿也是被大仓库磨没了脾气。alias 那步我后来撤回了,有个 CI 脚本悄悄依赖 grep 的老行为,硬换成 rg 它直接翻脸不认人。现在终端手敲用 rg,正经脚本里还是写全路径,图个踏实。

lazy
[链接]

alias grep='rg’我早年也这么干过 后来几个老脚本里grep专属的flag rg不认 直接报错 又默默卸了别名hh

bookworm_96
[链接]

你说的"并行正则引擎"这个说法稍微有点不严谨,想补充一下。rg 快的核心其实不是把正则匹配本身做成了并行——它对单个文件内容的搜索在常规构建下是单线程的——真正的加速来自三块:一是默认读 .gitignore,直接跳过 node_modules、build 这类目录,你那个"倒杯水回来还在转"的体验,省掉的主要是这些噪音而不是引擎本身;二是目录遍历是多线程的(parallel traversal);三是用 SIMD 加速的字面量扫描,能先快速排除整文件都不含关键词的情况。

BurntSushi 的 benchmark 里有个挺说明问题的现象:在带 node_modules 的真实 repo 里 rg 比裸 grep 快几十倍,但给裸 grep 加上等价的 exclude 之后,差距就缩到个位数倍了。换句话说,很多"落差感"来自默认行为的差异,不全是 engine 的锅。
其实
另外 alias grep=‘rg’ 我建议只放在交互 shell 的 rc 里,别进全局 profile。老脚本里不少依赖 grep 特定的输出格式和 flag,rg 在 -r、–include 这些地方行为不完全一致,真塞成全局别名容易踩坑。我自己在 zsh 里 alias 了,但脚本一律写死 /bin/grep,这样最稳。

嗯你那个"每天省几十次等待"的账算得挺实在。顺便安利个 fd,替代 find,同样 gitignore 友好、语法短,跟 rg 一个路子。

euler_cat
[链接]

你这个"并行正则引擎"的说法,我得稍微纠一下。rg 快的主因其实不是把正则本身并行化了——单文件内的匹配它还是串行的。im Grunde,真正并行的是目录遍历那一层,多个文件同时扫。

真正让它碾压 grep 的是另外两点:一是默认就按 .gitignore 跳过噪音,省掉大量无谓的 IO;二是它用的 regex 引擎走 DFA 有限自动机那一路,不像走 PCRE 的实现那样在某些 pattern 上 catastrophic backtracking,碰到坏表达式也是线性时间跑完,不会卡死。

所以你那个"几百万行大仓库秒回"的场景,收益的很大一块其实是"少读了文件",而不是"读得更快"。要是换成一个单独的超大单文件,gap 就没这么夸张了。

另外 alias grep=‘rg’ 我踩过坑。交互用基本没事,但 rg 默认不碰隐藏文件和 . 开头的目录,而 grep 会。哪天脚本里靠 grep 扫 .git 或某个 dotfile 目录,rg 就静悄悄地漏结果,还不好查。我后来只在交互 shell 里 alias,正经脚本老老实实写 grep。还有 rg 默认递归,裸 grep foo 和裸 rg foo 语义也不同。

fd 和 bat 跟 rg 是一家的,配起来找文件、看内容都顺手,可以试试。

stone
[链接]

以前我也跟楼主一样,觉得grep够用就懒得换。后来有回查一个几百万行的老项目,命令敲下去去吃个饭,回来它还在那转,才狠下心试了rg,那速度落差确实跟你说的一样爽。坦白讲

不过有一说一,rg默认跳过那些噪音目录是真省心,可真碰上要在压缩包、或者一些奇奇怪怪编码的老文件里翻东西,grep加一串参数还是绕不开。工具这东西,顺手就行,没必要为了追新把整个习惯打乱。

我shell里倒没敢直接alias grep=‘rg’。有些老脚本里grep的某些行为rg并不完全一致,怕哪天silent地踩了坑。你现在是只在交互终端这么配,还是连脚本环境也一起换了?

vim57
[链接]

alias grep=‘rg’ 得留个心眼,有些老脚本吃 GNU grep 的

tender_2006
[链接]

当年我也吃过grep的亏,下楼取个快递回来它还在转。换rg顺手太多,顺带安利个bat,看代码带高亮比cat舒服

feynman1
[链接]

alias grep=‘rg’ 这步我得泼点冷水。rg 默认就递归,所以平时敲 rg 关键词确实爽;但 grep 的 -r 是"递归",rg 的 -r 却是 ‘–replace’(替换匹配内容)。你那些写了 grep -r xxx file 的老脚本一旦套上这个 alias,语义当场错位,而且报错不一定明显,排查起来很隐蔽。我前阵子就吃过这个亏,后来乖乖把 alias 限在交互命令行里,脚本里一律写全路径的 grep。

至于"并行正则引擎"这个说法,严格讲不太准。rg 快主要靠文件遍历并行化,单个文件内部的匹配仍是串行的,底层 regex crate 还不支持回溯引用和 look

quant
[链接]

alias grep='rg’这步我之前也照做了,后来发现没帖子里说的那么无脑。rg默认就递归、默认smart-case,正则又是Rust regex那套而非grep的BRE/ERE,有些依赖旧行为的老脚本和pipeline会悄悄跑偏。从某种角度看,alias交互用挺香,脚本里还是写全命令比较稳。

oak39
[链接]

我前阵子在这版也发过一帖说弃了grep,看来被大仓库磨过性子的人不少。就是 alias 那步我留了个心眼,有些老脚本吃的是 grep 那套退出码和参数脾气,真全换成 rg,哪天 CI 悄无声息挂了都不好排查。

dr__jp
[链接]

我也在用 rg,你说的那种"倒杯水回来 grep 还在转"的落差感太真实了。不过技术细节上有一点想补一下。

你说 rg 是"并行正则引擎",这个讲法稍微有点不严谨。ripgrep 的快主要两块:一是它用的 Rust regex crate 本身实现高效,有限自动机加 SIMD,对纯字面量匹配还有专门优化;二是它在"遍历文件"这一层做了多线程,同时开多个文件并行搜。但单文件内的正则匹配本身并不是并行跑的。所以更准确的说法大概是"多线程文件搜索配一套高效的单线程正则",而不是正则引擎自己在并行。

另外 “alias grep=‘rg’ 就完事、老脚本不用改” 这点我建议留个心眼。rg 默认跳过隐藏文件、按 .gitignore 过滤,grep 默认不跳。严格来说哪天你脚本里指望 grep 去翻 .git 目录或者某个点开头的配置,alias 一挂就什么都搜不到了。我自己是交互用 rg、脚本里老老实实写 grep,两条腿分开走更稳。

fd 你试过没,跟 rg 配着用挺顺手。

[首页] [上篇] 第 1 / 1 页 [下篇] [末页] [回复]
需要登录后才能回复。[去登录]
回复此帖进入修真世界