我正在从一个大型二进制文件(1 TB)中提取一个十六进制模式(当前是一个数字)
xxd -p /path/to/sda.img | tr -d '\n' | grep -ob '117a0cb17ada1002'
Run Code Online (Sandbox Code Playgroud)
我想知道为什么grep
最多使用 7 GB RAM 然后崩溃并显示没有更多 RAM 可用的错误消息(我有更多(16 GB + 8 GB 交换),但我收到了消息)。我的问题是
grep
如果不需要记住任何东西,为什么要使用这么多内存(搜索结果立即打印到标准输出(没有输出,所以我假设没有搜索结果,在较小的文件上搜索结果已显示)立即地)?grep
替代(一组)命令来完成相同的任务,我怎么能防止这种内存使用?我删除\n
以获得正确的字节偏移量。我想知道文件中的位置/没有分隔符的一行没有大量计算(减去插入的换行符等)。
我grep
在 Ubuntu 14.10 amd64 上运行2.20-3。
由于grep
逐行匹配,内存不足,并且您已明确删除管道中的所有换行符:
$ xxd -p /path/to/sda.img | tr -d '\n' | grep -ob '117a0cb17ada1002'
Run Code Online (Sandbox Code Playgroud)
我假设您想要做的是在 的输出中找到特定十六进制字符串的字节偏移量xxd
,并确保您找到它(如果它存在),您删除换行符(否则字符串可能跨越两行)。
以下awk
脚本将跨连续行匹配模式并将匹配的第一个字符的位置打印到终端。它假设输入正好是 60 个字符宽(就像输出一样xxd -p
)。
{
if (NR > 1 && offset = match(line $0, pattern)) {
printf("%d: %s\n", (NR - 2)*60 + offset, pattern);
}
line = $0;
}
Run Code Online (Sandbox Code Playgroud)
或者,或者(但等效地):
NR > 1 {
if (offset = match(line $0, pattern)) {
printf("%d: %s\n", (NR - 2)*60 + offset, pattern);
}
}
{ line = $0 }
Run Code Online (Sandbox Code Playgroud)
在随机输入数据上测试它(我正在使用的搜索字符串在数据中突出显示):
$ xxd -p random.dat | 头-n 5 b1a632f5 218b1404d9873dc20ae80e687c99c618bfc0f92db007c36c 2888 21a9 9d23914e34510b9ab8e1c2b340cf1e4a0585b788aecbbc64f01a7a52 62e1746ca1fa4ff65d575419522d52169c5d3f9eee0e204979d79634db9b fa78320eb7b9e072adc53720785fc7b65a1ffb04cc77566686ea74 ac00fe f3 2afc1539690d0046bc13706404d82112442d4bc447ac95df1fe96cd4bd
$ xxd -p random.dat | awk -v pattern=b1a632f5 -f script.awk
1: b1a632f5
$ xxd -p random.dat | awk -v pattern=288821a9 -f script.awk
57: 288821a9
$ xxd -p random.dat | awk -v pattern=ac00fef3 -f script.awk
235: ac00fef3
Run Code Online (Sandbox Code Playgroud)
无论如何,在 1 TB 的大文件上运行它会很慢。它可以(可能)通过提供-c 256
选项xxd
(并相应地在awk
脚本中将 60 更改为 256 )以减少模式匹配的数量来加快速度,但是每行上的数据必须至少匹配两次(一次一起与上一行,一次与下一行一起)。