我用来搜索某些十六进制值的当前命令(比如0A 8b 02
)涉及:
find . -type f -not -name "*.png" -exec xxd -p {} \; | grep "0a8b02" || xargs -0 -P 4
考虑到以下目标,是否有可能改善这一目标:
.png
个文件)如果xargs
正在为4个处理器正常工作,我不太自信。此外,当grep
找到匹配项时,我在打印文件名时遇到了困难,因为它是从xxd
传来的。有什么建议吗?
答案 0 :(得分:2)
如果:
grep
0xa
) [1]
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
一起使用,除了报告的字节偏移总是 start 的行模式匹配。
换句话说:如果文件中没有换行符,则字节偏移量才会正确。
此外,BSD grep
不支持将NUL(0x0
)个字节指定为搜索字符串的一部分,即使通过-f
的文件提供也不支持。
grep
&#,没有并行处理,但只有少数 find
次调用39; s -exec ... +
,与xargs
一样,会同时传递尽可能多的文件名到命令行grep
。grep
直接搜索字节序列,不需要xxd
:
-F
),这更快
链接的文章来自bash
手册,但它们也适用于zsh
(以及ksh
)。
-P
(支持PRCE,Perl兼容的正则表达式)和非预扩展的转义序列,但这将是更慢:{{ 1}} grep -PHoab '\x{0e}\x{8b}\x{02}'
确保LC_ALL=C
将每个字节视为自己的字符,而不应用任何编码规则。grep
将搜索字符串视为文字(而不是正则表达式)-F
将相关的输入文件名添加到每个输出行;请注意,当给出多于1个文件名参数时,Grep会隐式执行此操作-H
仅报告匹配的字符串(字节序列),而不是整行(无论如何,行的概念在二进制文件中没有意义) [2] -o
将二进制文件视为文本文件(如果不是这样,Grep只会为匹配的二进制输入文件打印文本-a
)Binary file <filename> matches
报告匹配的字节偏移量如果在给定的输入文件中找到最多 1 匹配就足够了,请添加-b
。
[1]无法使用换行符,因为Grep总是将搜索模式字符串中的换行符视为分隔多个搜索模式。另外,Grep是基于 line 的,所以你不能跨行匹配; GNU Grep的-m 1
选项将输入分割为NUL字节可能有所帮助,但前提是您的搜索字节序列不包含NUL字节;您还必须将正则表达式中的转义序列与-null-data
结合起来表示您的字节值 - 因为您需要使用转义符序列-P
代替实际换行符。
[2] \n
使-o
报告匹配的字节偏移量,而不是行开头的字节偏移量(如上所述,不幸的是,BSD Grep 总是做后者);此外,仅在此处报告匹配本身是有益的,因为尝试打印整行将导致不可预测的长输出行,因为二进制文件中没有行的概念;但是,无论哪种方式,从二进制文件输出字节都可能导致终端出现奇怪的渲染行为。