如果:
- 你有GNU
grep
- 并且您搜索的十六进制字节从不包含换行符 (
0xa
) [1]
- 如果它们包含 NUL (
0x
),您必须grep
通过文件 ( -f
) 而不是直接参数提供搜索字符串。
下面的命令会带你到那里,使用搜索的例子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
该grep
命令产生如下输出行:
<filename>:<byte-offset>:<matched-bytes>
然后LC_ALL=C cut -d: -f1-2
减少到<filename>:<byte-offset>
该命令几乎可以与BSD grep
一起使用,除了报告的字节偏移量总是与模式匹配的行的开头。
换句话说:仅当文件中的匹配项之前没有换行符时,字节偏移量才会正确。
此外,BSDgrep
不支持将 NUL ( 0x0
) 字节指定为搜索字符串的一部分,即使通过带有-f
.
- 请注意,不会有并行处理,但只有少数
grep
调用,基于使用find
's -exec ... +
,就像's 一样xargs
,一次传递尽可能多的文件名以适合命令行grep
。
- 通过
grep
直接搜索字节序列,不需要xxd
:
- 该序列被指定为一个ANSI C-quoted string,这意味着转义序列被shell扩展为文字,使 Grep 能够将结果字符串作为文字(via
-F
) 进行搜索,这样更快。
链接的文章来自bash
手册,但它们也适用于zsh
(and ksh
)。
- 一个 GNU Grep 替代方案是使用
-P
(支持 PRCE,Perl 兼容的正则表达式)与非预扩展转义序列,但这会更慢:grep -PHoab '\x{0e}\x{8b}\x{02}'
LC_ALL=C
确保在不应用任何编码规则的情况下grep
将每个字节视为自己的字符。
-F
将搜索字符串视为文字(而不是正则表达式)
-H
将相关的输入文件名添加到每个输出行;请注意,当给出超过 1 个文件名参数时,Grep 会隐式执行此操作
-o
只报告匹配的字符串(字节序列),而不是整行(无论如何,一行的概念在二进制文件中没有意义)[2]
-a
将二进制文件视为文本文件(没有这个,Grep 只会Binary file <filename> matches
为匹配的二进制输入文件打印文本)
-b
报告匹配的字节偏移量
如果在给定的输入文件中最多可以找到1 个-m 1
匹配项,则添加.
[1] 不能使用换行符,因为 Grep 总是将搜索模式字符串中的换行符视为分隔多个搜索模式。另外,Grep 是基于行的,所以你不能跨行匹配;GNU Grep-null-data
将输入拆分为 NUL 字节的选项可能会有所帮助,但前提是您的搜索字节序列也不包含 NUL 字节;您还必须将字节值表示为正则表达式中的转义序列,并结合- 因为您需要使用转义序列来代替实际的换行符。-P
\n
[2]-o
需要-b
报告匹配的字节偏移量而不是行首的字节偏移量(如上所述,不幸的是,BSD Grep总是执行后者);此外,在此处仅报告匹配项本身是有益的,因为尝试打印整行会导致无法预料的长输出行,因为二进制文件中没有行的概念;但是,无论哪种方式,从二进制文件输出字节都可能导致终端出现奇怪的渲染行为。