为什么要学习riggrep?

Riggrep快

天下武功,唯快不破

Riggrep聪明

默认会排除 .gitignore/.ignore/.rgignore 文件下的配置和隐藏文件、二进制文件

安装

1
brew install ripgrep

使用说明

样例所有操作使用 study-sample 仓库,里面是常用语言的入门学习资源,操作文档结构如下:

1
tree ~/github/study-sample
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
/Users/tomyli/github/study-sample
|-- LearnBash.sh
|-- LearnJava.java
|-- README.md
|-- commonlisp.lisp
|-- learn-emacs-lisp.el
|-- learn.nix
|-- learnc.c
|-- learnclojure.clj
|-- learngo.go
|-- learnlua.lua
|-- learnpython.py
|-- learnrust.rs
`-- markdown.md

0 directories, 13 files

基本使用

遍历查询 ~/github/study-sample/ 下所有包含 TODO say hello 字符串的结果

1
rg 'TODO say hello' ~/github/study-sample/
1
2
3
4
5
6
7
/Users/tomyli/github/study-sample/learnc.c:/* TODO say hello */
/Users/tomyli/github/study-sample/commonlisp.lisp:;; TODO say hello
/Users/tomyli/github/study-sample/learnclojure.clj:;; TODO say hello
/Users/tomyli/github/study-sample/learn-emacs-lisp.el:;; TODO say hello
/Users/tomyli/github/study-sample/LearnBash.sh:# TODO say hello
/Users/tomyli/github/study-sample/LearnJava.java: // TODO say hello
/Users/tomyli/github/study-sample/learnrust.rs:// TODO say hello

查询到的结果以 文件 维度进行展示,使用 分号 进行分割,分号前为文件路径,分号后为查询匹配到的内容

只打印路径不打印匹配的内容

如果只关注匹配的文件不关注内容,可以使用 –files-with-match 选项,短选项为 -l

1
rg -l 'TODO say hello' ~/github/study-sample/
1
2
3
4
5
6
7
/Users/tomyli/github/study-sample/LearnJava.java
/Users/tomyli/github/study-sample/learnclojure.clj
/Users/tomyli/github/study-sample/learn-emacs-lisp.el
/Users/tomyli/github/study-sample/learnc.c
/Users/tomyli/github/study-sample/commonlisp.lisp
/Users/tomyli/github/study-sample/LearnBash.sh
/Users/tomyli/github/study-sample/learnrust.rs

上述结果只显示了匹配的文件路径,不再包含内容

搜索结果进行排序

为了性能考虑,rg默认搜索结果是无序的,如果想让结果有序,可增加 –sort path 选项

1
rg -l 'TODO say hello' --sort path ~/github/study-sample/
1
2
3
4
5
6
7
/Users/tomyli/github/study-sample/LearnBash.sh
/Users/tomyli/github/study-sample/LearnJava.java
/Users/tomyli/github/study-sample/commonlisp.lisp
/Users/tomyli/github/study-sample/learn-emacs-lisp.el
/Users/tomyli/github/study-sample/learnc.c
/Users/tomyli/github/study-sample/learnclojure.clj
/Users/tomyli/github/study-sample/learnrust.rs

上述输出将结果按字母进行排序

搜索不包含指定内容

如果想查询不包含指定内容的文件,可以使用 –files-without-match 选项,此选项无缩写选项

1
rg --files-without-match 'TODO say hello' --sort path ~/github/study-sample/
1
2
3
4
5
6
/Users/tomyli/github/study-sample/README.md
/Users/tomyli/github/study-sample/learn.nix
/Users/tomyli/github/study-sample/learngo.go
/Users/tomyli/github/study-sample/learnlua.lua
/Users/tomyli/github/study-sample/learnpython.py
/Users/tomyli/github/study-sample/markdown.md

以上结果正好与上一项的搜索结果相反

搜索包含指定表达式的内容

rg查询默认支持按表达式进行搜索,如想搜索所有不包含var或者let或者const内容

1
rg --files-without-match "\b(var|let|const)\b" --sort path ~/github/study-sample/
1
2
/Users/tomyli/github/study-sample/README.md
/Users/tomyli/github/study-sample/learnlua.lua

为什么没有JAVA文件,因为java在10以后已经支持 var 关键字了

搜索表达式 \b(var|let|const)\b 说明

  1. \b 表示匹配一个单词
  2. | 表示或者

固定String搜索

默认rg使用正则表达式模式进行搜索,如果想搜索所有带 ? a 的文件,直接进行 rg “? a” 会报错,正确的做法是使用 -F 选项,指定rg使用固定字符串方式搜索

1
rg -F "? a" ~/github/study-sample/
1
/Users/tomyli/github/study-sample/learn.nix:  ({ a = 1; b = 2; } ? a)

按指定文件类型搜索

在指定文件类型搜索

如果只想搜索指定类型下的内容,则可以使用 -t filetype 选项,如只想搜索java类型文件下的内容

1
rg -tjava 'TODO say hello' ~/github/study-sample/
1
/Users/tomyli/github/study-sample/LearnJava.java: // TODO say hello

排除指定文件类型搜索

如果想搜索非指定类型下的内容,则可以使用 -T filetype 选项,如排除搜索java文件下的内容

1
rg -Tjava 'TODO say hello' ~/github/study-sample/
1
2
3
4
5
6
/Users/tomyli/github/study-sample/commonlisp.lisp:;; TODO say hello
/Users/tomyli/github/study-sample/learnc.c:/* TODO say hello */
/Users/tomyli/github/study-sample/learn-emacs-lisp.el:;; TODO say hello
/Users/tomyli/github/study-sample/learnclojure.clj:;; TODO say hello
/Users/tomyli/github/study-sample/LearnBash.sh:# TODO say hello
/Users/tomyli/github/study-sample/learnrust.rs:// TODO say hello

rg支持的文件类型

rg支持的文件类型可以通过 rg –type-list 进行获取,如查询java类型的文件

1
rg --type-list | grep java
1
java: *.java, *.jsp, *.jspx, *.properties

对于 -tjava 类型, 它是会匹配到 .java, .jsp, .jspx, .properties 文件的

只搜索指定文件格式的内容

按类型搜索的范围有点大,如果只想在 .java 结尾的文件中进行搜索,可以使用 glob 模式,指定 -g 选项

1
rg -g "*.java" 'TODO say hello' ~/github/study-sample/
1
/Users/tomyli/github/study-sample/LearnJava.java: // TODO say hello

排除搜索指定文件类型

1
rg -g "!*.java" 'TODO say hello' ~/github/study-sample/
1
2
3
4
5
6
/Users/tomyli/github/study-sample/learnclojure.clj:;; TODO say hello
/Users/tomyli/github/study-sample/commonlisp.lisp:;; TODO say hello
/Users/tomyli/github/study-sample/learnc.c:/* TODO say hello */
/Users/tomyli/github/study-sample/learn-emacs-lisp.el:;; TODO say hello
/Users/tomyli/github/study-sample/learnrust.rs:// TODO say hello
/Users/tomyli/github/study-sample/LearnBash.sh:# TODO say hello

查询并替换

rg不仅支持查找,还支持替换,使用 –replace 选项,短选项为 -r, 比如把 TODO say hello 替换成 DONE say hello

1
rg -g "!*.java" 'TODO say hello' ~/github/study-sample/ -r 'DONE say hello'
1
2
3
4
5
6
/Users/tomyli/github/study-sample/commonlisp.lisp:;; DONE say hello
/Users/tomyli/github/study-sample/learnclojure.clj:;; DONE say hello
/Users/tomyli/github/study-sample/learn-emacs-lisp.el:;; DONE say hello
/Users/tomyli/github/study-sample/learnc.c:/* DONE say hello */
/Users/tomyli/github/study-sample/learnrust.rs:// DONE say hello
/Users/tomyli/github/study-sample/LearnBash.sh:# DONE say hello

替换后验证一下

1
rg -g "!*.java" 'TODO say hello' ~/github/study-sample/
1
2
3
4
5
6
/Users/tomyli/github/study-sample/commonlisp.lisp:;; TODO say hello
/Users/tomyli/github/study-sample/learnc.c:/* TODO say hello */
/Users/tomyli/github/study-sample/learn-emacs-lisp.el:;; TODO say hello
/Users/tomyli/github/study-sample/learnclojure.clj:;; TODO say hello
/Users/tomyli/github/study-sample/learnrust.rs:// TODO say hello
/Users/tomyli/github/study-sample/LearnBash.sh:# TODO say hello

还是可以查询到 TODO say hello , 这是因为rg只会对 输出的结果进行替换,不会去修改原文件

输出样式

rg支持输出样式配置,可以直接使用 -p 选项, -p–color always –heading –line-number 选项集合的缩写

1
rg -g "!*.java" 'TODO say hello' ~/github/study-sample/ -p
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
/Users/tomyli/github/study-sample/learn-emacs-lisp.el
63:;; TODO say hello

/Users/tomyli/github/study-sample/learnclojure.clj
9:;; TODO say hello

/Users/tomyli/github/study-sample/learnc.c
11:/* TODO say hello */

/Users/tomyli/github/study-sample/commonlisp.lisp
8:;; TODO say hello

/Users/tomyli/github/study-sample/LearnBash.sh
7:# TODO say hello

/Users/tomyli/github/study-sample/learnrust.rs
15:// TODO say hello

以上就显示了行号与标题,还可以在支持色彩的终端显示不同颜色

替换查询并保存修改到文件

1
rg -l -g "!*.java" 'TODO say hello' ~/github/study-sample/ | xargs sed -i '' 's/TODO/DONE/g'

再验证一下

执行以下查询,没有结果返回,因为已经把 TODO 替换成 DONE

1
rg -g "!*.java" 'TODO say hello' ~/github/study-sample/

那查询一下 DONE say hello 是会有结果输出的

1
rg -g "!*.java" 'DONE say hello' ~/github/study-sample/
1
2
3
4
5
6
/Users/tomyli/github/study-sample/LearnBash.sh:# DONE say hello
/Users/tomyli/github/study-sample/learn-emacs-lisp.el:;; DONE say hello
/Users/tomyli/github/study-sample/learnclojure.clj:;; DONE say hello
/Users/tomyli/github/study-sample/learnc.c:/* DONE say hello */
/Users/tomyli/github/study-sample/commonlisp.lisp:;; DONE say hello
/Users/tomyli/github/study-sample/learnrust.rs:// DONE say hello

还原对文件的修改

1
2
cd ~/github/study-sample/
git restore .

参考

https://github.com/BurntSushi/ripgrep/blob/master/GUIDE.md#common-options

Fast Searching with ripgrep — Marius Schulz