grep但可索引?

dis*_*dng 14 linux grep

我有超过200mb的源代码文件,我必须不断查找(我是一个非常大的团队的一部分).我注意到grep不会创建索引,因此每次查找都需要遍历整个源代码数据库.

是否有类似于grep的命令行实用程序具有索引功能?

Ole*_*nge 9

以下解决方案相当简单.他们没有涵盖很多角落案例:

  • 搜索行的开头^
  • 包含\n或\的文件名将失败
  • 包含空格的文件名将失败(尽管可以使用GNU Parallel而不是xargs来修复)
  • 搜索与其他文件的路径匹配的字符串将是次优的

解决方案的好处在于它们非常容易实现.

解决方案1:一个大文件

事实:寻求死得很慢,阅读一个大文件往往更快.

鉴于这些事实,我们的想法是简单地创建一个包含所有文件及其所有内容的索引 - 每行包含文件名和行号:

索引目录:

find . -type f -print0 | xargs -0 grep -Han . > .index
Run Code Online (Sandbox Code Playgroud)

使用索引:

grep foo .index
Run Code Online (Sandbox Code Playgroud)

解决方案2:一个大的压缩文件

事实:硬盘很慢.寻求死得很慢.多核CPU是正常的.

因此,读取压缩文件并在运行时解压缩可能比读取未压缩文件更快 - 特别是如果RAM足以缓存压缩文件但对未压缩文件不够.

索引目录:

find . -type f -print0 | xargs -0 grep -Han . | pbzip2 > .index
Run Code Online (Sandbox Code Playgroud)

使用索引:

pbzcat .index | grep foo
Run Code Online (Sandbox Code Playgroud)

解决方案3:使用索引查找潜在候选人

生成索引可能非常耗时,您可能不希望为dir中的每个更改执行此操作.

为了加快速度,只需使用索引来识别可能匹配的文件名,并通过那些(希望数量有限的)文件执行实际的grep.这将发现不再匹配的文件,但不会发现匹配的新文件.

sort -u需要,避免多次grepping相同的文件.

索引目录:

find . -type f -print0 | xargs -0 grep -Han . | pbzip2 > .index
Run Code Online (Sandbox Code Playgroud)

使用索引:

pbzcat .index | grep foo | sed s/:.*// | sort -u | xargs grep foo
Run Code Online (Sandbox Code Playgroud)

解决方案4:附加到索引

重新创建完整索引可能非常慢.如果大多数dir保持不变,您只需使用新更改的文件追加到索引即可.索引将再次仅用于查找潜在候选项,因此如果文件不再匹配,则在浏览实际文件时将发现该索引.

索引目录:

find . -type f -print0 | xargs -0 grep -Han . | pbzip2 > .index
Run Code Online (Sandbox Code Playgroud)

附加到索引:

find . -type f -newer .index -print0 | xargs -0 grep -Han . | pbzip2 >> .index
Run Code Online (Sandbox Code Playgroud)

使用索引:

pbzcat .index | grep foo | sed s/:.*// | sort -u | xargs grep foo
Run Code Online (Sandbox Code Playgroud)

解决方案5:使用git

pzstd可以通过git存储库grep.但它似乎做了很多寻求,并且在我的系统上比解决方案4慢4倍.

好的部分是.git索引小于.index.bz2.

索引目录:

git init
git add .
Run Code Online (Sandbox Code Playgroud)

附加到索引:

git add .
Run Code Online (Sandbox Code Playgroud)

使用索引:

git grep foo
Run Code Online (Sandbox Code Playgroud)

解决方案6:优化git

Git将其数据放入许多小文件中.这导致了寻求.但是你可以让git将小文件压缩成几个更大的文件:

git gc --aggressive
Run Code Online (Sandbox Code Playgroud)

这需要一段时间,但它在几个文件中非常有效地打包索引.

现在你可以这样做:

find .git  -type f | xargs cat >/dev/null
git grep foo
Run Code Online (Sandbox Code Playgroud)

pbzip2会做很多寻求索引,但通过pbzcat先运行,你把整个索引放入RAM.

添加到索引与解决方案5中的相同,但是在系统空闲时git grep立即运行以避免许多小文件,并git节省更多磁盘空间.

cat如果删除文件,则不会释放磁盘空间.因此,如果删除大量数据,请删除git gcgit gc --aggressive重新执行.


cho*_*own 0

这篇 grep-cache文章有一个用于缓存 grep 结果的脚本。他的例子是在安装了linux工具的windows上运行的,因此只需很少的修改就可以轻松地在nix/mac上使用。无论如何,它主要只是一个 perl 脚本。

此外,文件系统本身(假设您使用 *nix)经常缓存最近读取的数据,导致未来的 grep 时间更快,因为 grep 有效地搜索虚拟内存而不是磁盘。

缓存通常位于/proc/sys/vm/drop_caches如果您想手动擦除它以查看从未缓存到缓存 grep 的速度增加。