如果:
- 您有GNU
grep
- 并且您搜索的十六进制字节从不包含换行符(
0xa
)[1]
- 如果它们包含NUL(
0x
),则必须通过文件(-f
)而不是直接参数提供grep
搜索字符串。
以下命令将帮助您使用搜索0e 8b 02
的示例:
LC_ALL=C find . -type f -not -name "*.png" -exec grep -FHoab $'\x{0e}\x{8b}\x{02}' {} + |
LC_ALL=C cut -d: -f1-2
< p >
grep
命令的输出行如下:
<filename>:<byte-offset>:<matched-bytes>
LC_ALL=C cut -d: -f1-2
将其缩小为<filename>:<byte-offset>
该命令在使用BSDgrep
时几乎可以正常工作,但是报告的字节偏移始终是匹配模式所在行的开头。
换句话说:如果文件中有换行符在匹配之前,则字节偏移将不正确。
此外,BSD grep
不支持将NUL(0x0
)字节作为搜索字符串的一部分进行指定,即使通过-f
提供文件也不支持。
请注意,这里没有并行处理,只有一些基于使用find的-exec ... +的grep调用,类似于xargs,一次将尽可能多的文件名传递给grep。通过让grep直接搜索字节序列,无需使用xxd:
该序列被指定为
ANSI C-quoted string,这意味着转义序列由shell扩展为文字,使Grep能够搜索结果字符串作为文字(通过-F),这样更快。
LC_ALL=C确保grep将每个字节视为自己的字符而不应用任何编码规则。
-F将搜索字符串视为文字(而不是正则表达式)
-H在每个输出行之前添加相关输入文件名;当给出多个文件名参数时,Grep会隐式执行此操作
-o仅报告匹配的字符串(字节序列),而不是整个行(在二进制文件中,行的概念没有意义)
[2]
-a将二进制文件视为文本文件进行处理(如果没有此选项,则对于具有匹配项的二进制输入文件,Grep只会打印文本Binary file matches)
-b报告匹配项的字节偏移量
如果在给定的输入文件中找到至多
1个匹配项足够了,那么请添加
-m 1
。
[1] 由于Grep总是将搜索模式字符串中的换行符视为分隔多个搜索模式,因此不能使用换行符。另外,Grep是基于行的,所以您无法跨行匹配;GNU Grep的-null-data
选项可以通过NUL字节拆分输入,但仅当您的搜索字节序列不包含NUL字节时才有效;您还必须在与-P
结合使用的正则表达式中表示您的字节值为转义序列,因为您需要使用转义序列\n
代替实际的换行符。
[2] 需要使用 -o
选项才能使 -b
报告匹配的字节偏移量,而不是报告行开头的偏移量(如上所述,BSD Grep 总是报告后者,不幸的是);此外,仅报告匹配本身在这里是有益的,因为尝试打印整个行将导致输出行长度不可预测,因为二进制文件中没有行的概念;无论如何,在终端中输出二进制文件的字节可能会导致奇怪的渲染行为。
find | xargs
中使用该脚本。由于您使用的是 zsh,因此在子shell中定义函数很困难。如果您决定将所有内容放在一个脚本中,可以改用 bash,它允许您导出函数。 - 4ae1e10xa
(即换行符),那么会有一个相当简单的解决方案 - 但听起来它们可以包括,对吗?此外,您是否使用 GNU 工具(Linux)? - mklement00xa
,不幸的是我正在 OS X 上运行。这会成为问题吗? - Helen Chegrep
对您来说是一个选择。请查看我的答案,让我们在那里继续讨论。 - mklement0