如何转储二进制文件的一部分

我有二进制,并且想要提取它的一部分,从知道字节string(即FF D8 FF D0),并以已知字节string(AF FF D9)结束,

在过去,我用dd从开始/结束切割二进制文件的一部分,但这个命令似乎不支持我问。

terminal上的什么工具可以做到这一点?

Solutions Collecting From Web of "如何转储二进制文件的一部分"

在单个管道中:

 xxd -c1 -p file | awk -vb="ffd8ffd0" -ve="aaffd9" ' found == 1 { print $0 str = str $0 if (str == e) {found = 0; exit} if (length(str) == length(e)) str = substr(str, 3)} found == 0 { str = str $0 if (str == b) {found = 1; print str; str = ""} if (length(str) == length(b)) str = substr(str, 3)} END{ exit found }' | xxd -r -p > new_file test ${PIPESTATUS[1]} -eq 0 || rm new_file 

这个想法是在两个xxd之间使用awk来选择需要的文件的一部分。 一旦找到第一个模式, awk打印字节,直到找到第二个模式并退出。

第一种模式被发现但第二种模式不是必须被考虑在内的情况。 它在awk脚本的END部分完成,它返回一个非零的退出状态。 这是由bash${PIPESTATUS[1]}捕获的,我决定删除这个新文件。

请注意,空文件也意味着什么都没有找到。

找到开始/结束位置,然后提取范围。

 $ xxd -g0 input.bin | grep -im1 FFD8FFD0 | awk -F: '{print $1}' 0000cb0 $ ^FFD8FFD0^AFFFD9^ 0009590 $ dd ibs=1 count=$((0x9590-0xcb0+1)) skip=$((0xcb0)) if=input.bin of=output.bin 

这应该使用标准工具(xxd,tr,grep,awk,dd)。 这正确地处理了“跨线模式分割”问题,也查找只在字节偏移(不是半字节)对齐的模式。

 file=<yourfile> outfile=<youroutputfile> startpattern="ff d8 ff d0" endpattern="af ff d9" xxd -g0 -c1 -ps ${file} | tr '\n' ' ' > ${file}.hex start=$((($(grep -bo "${startpattern}" ${file}.hex\ | head -1 | awk -F: '{print $1}')-1)/3)) len=$((($(grep -bo "${endpattern}" ${file}.hex\ | head -1 | awk -F: '{print $1}')-1)/3-${start})) dd ibs=1 count=${len} skip=${start} if=${file} of=${outfile} 

注意:上面的脚本使用临时文件来防止二进制>十六进制转换两次。 空间/时间的权衡是将xxd的结果直接传递给两个grep 。 单线也是可能的,代价是清晰。

也可以使用tee和命名管道来防止存储一个临时文件和转换输出两次,但我不知道它会更快(xxd是快速的),而且写得更加复杂。

看到这个链接进行二进制grep的方法。 一旦你有开始和结束抵消,你应该能够与dd得到你所需要的。

awk解决方案中的一种变体,假定您的二进制文件(一旦用空格转换为十六进制)适合内存:

 xxd -c1 -p file | tr "\n" " " | sed -n -e 's/.*\(ff d8 ff d0.*aa ff d9\).*/\1/p' | xxd -r -p > new_file 

sed另一个解决方案,但使用较少的内存:

 xxd -c1 -p file | sed -n -e '1{N;N;N}' -e '/ff\nd8\nff\nd0/{:begin;p;s/.*//;n;bbegin}' -e 'N;D' | sed -n -e '1{N;N}' -e '/aa\nff\nd9/{p;Q1}' -e 'P;N;D' | xxd -r -p > new_file test ${PIPESTATUS[2]} -eq 1 || rm new_file 

第一个sed打印从ff d8 ff d0直到文件结尾。 请注意,您需要在-e '1{N;N;N}'尽可能多的N ,因为第一个模式中的字节少一个

第二个sed从文件的开头打印到aa ff d9 。 再次注意,你需要在-e '1{N;N}'尽可能多的N ,因为第二个模式中的字节少了一个

再次,需要测试是否找到第二个模式,如果不是,则删除文件。

请注意, Q命令是sed的GNU扩展。 如果没有,则需要在找到该模式后(在第一个sed ,但不打印文件的循环中) sed文件的其余部分,然后在十六进制到二进制转换后检查new_file以赖特模式。