grep 400GB 二进制文件最快的方法是什么?我需要 HDD 转储中的一个 txt 文件,并且我从中知道一些字符串,并且希望在转储中找到该文件。
我尝试使用,grep -a -C 10 searchstring
但是当 grep 尝试读取没有换行符的大块数据时,它会因内存不足而崩溃。另外我想不是从头开始搜索,而是从文件的某个点开始搜索
答案1
我会用strings
这种方式:
strings 400Gfile.bin | grep -C 10 searchstring
要从给定的偏移量(例如:20G)开始,
dd if=400Gfile.bin bs=20G skip=1 | strings | grep -C 10 searchstring
答案2
bgrep
我时不时地回到这个随机仓库:https://github.com/tmbinc/bgrep
根据自述文件“安装”:
curl -L 'https://github.com/tmbinc/bgrep/raw/master/bgrep.c' | gcc -O2 -x c -o $HOME/.local/bin/bgrep -
最小示例的示例用法:
printf '\x01\x02abcdabcd' > myfile.bin
bgrep -B2 -A2 6263 myfile.bin
输出:
myfile.bin: 00000003
\x02abc
myfile.bin: 00000007
dabc
因为6263
是bc
ASCII 格式,并且两个字节序列在零索引位置 3 和 7 处匹配。
让我们看看它是否可以处理不适合我的 Lnovo ThinkPad P51 的 32 GB 内存的大文件,并在我的 SSD 上进行了测试:
dd count=100M if=/dev/zero of=myfile.bin
printf '\x01\x02abcdabcd' >> myfile.bin
time bgrep -B2 -A2 6263 myfile.bin
输出:
myfile.bin: c80000003
\x02abc
myfile.bin: c80000007
dabc
real 11m26.898s
user 1m32.763s
sys 9m53.756s
所以花了一段时间但有效。
有点烦人的是不支持直接搜索明文字符,你必须给它一个十六进制字符串。但我们可以根据https://stackoverflow.com/questions/2614764/how-to-create-a-hex-dump-of-file-containing-only-the-hex-characters-without-spac
bgrep `printf %s bc | od -t x1 -An -v | tr -d '\n '` myfile.bin
所以 Bash 别名会有所帮助:
bgrepa() {
pat=$1
shift
bgrep `printf %s "$pat" | od -t x1 -An -v | tr -d '\n '` "$@"
}
bgrepa bc -B2 -A2 myfile.bin
不支持正则表达式。
在 Ubuntu 23.04 上测试,bgrep 28029c9203d54f4fc9332d094927cd82154331f2。
答案3
grep 的问题是它需要在内存中有一整行。如果该行太大以至于内存无法容纳,那么 grep 炸弹就会出现。解决这个困境的唯一方法是向 grep 提供小块。 (这实际上是 grep应该无论如何,它自己在做,但事实并非如此)。
使用dd
以便您可以指定起始偏移量,并使用fold
或grep --mmap
来避免在大于可用 RAM 的行上耗尽内存。grep --mmap
将防止系统避免阻塞,但可能会也可能不会阻止 grep 本身阻塞。这对于有人测试来说是一件好事。fold
将允许您定期插入换行符,这满足将输入拆分为可管理块的条件。
dd if=bigfile skip=xxx | fold | grep -b -a string
它-b
为您提供字节偏移量,您会发现它对于了解文本字符串在文件中的位置很有用。
我在我的一个 KVM 虚拟机管理程序上的 100GB 逻辑卷上对此进行了测试,使用搜索字符串“Hard”并在单独的窗口中运行 vmstat 来监控性能。逻辑卷基本上被格式化为安装了来宾 Linux VM 的硬盘驱动器(分区和文件系统)。对系统性能没有任何影响。它在大约 33 秒内处理了每个演出(当然,这会根据您的硬件而有很大差异)。
你说你想要快速的表现。这应该可以让您在 shell 脚本中使用实用程序时获得最快的性能。获得更快搜索的唯一方法是用 C 语言编写一个程序,该程序查找偏移量、读取指定的块大小、将该块输入到模式匹配算法中,然后再继续处理下一个块。似乎这种类型的“改进的 grep”应该已经存在,但在网上搜索我没有找到。
答案4
找到了一种 grep 巨大 JSON 文件(300Gb - 数据库导出)的方法,这实际上是一个文本,但没有任何换行符...问题是获取其中特定字段的字节偏移量。
使用 ugrep 解决并通过“tr”制作手动“行”。这样文件不会完全加载到内存中,ugrep 以“流式”方式工作,在命中时打印结果,并且字节偏移量是“原始”的 - 例如,可用于将 json 切成碎片。
cat ./full.json | tr '{' '\n' | ugrep --fixed-strings --byte-offset --format='%f:%b:%o%~' --binary --mmap -f ./splitstrings.txt