使用bash基于字符串位置“tailing”二进制文件?

3
我有一堆二进制文件,每个文件都包含一个嵌入在文件末尾但位置不同的字符串(每个文件中只出现一次)。我需要提取从该字符串位置开始到文件结束的部分并将其转储到新文件中。
例如,如果文件内容是“AWREDEDEDEXXXERESSDSDS”,感兴趣的字符串是“XXX”,那么我需要的文件部分是“XXXERESSDSDS”。
在 bash 中最简单的方法是什么?
6个回答

1
以下是一个小的hack shell解决方案,性能不是很高,但它可以工作。
按照以下方式编写脚本文件tail.sh
#!/bin/sh
dd bs=1 if=$1 of=$2 skip=`grep --binary-files=text -m1 -b -o $3 $1 | cut -d ':' -f 1 | head -1`

调用 tail.sh 输入文件名 输出文件名 模式

p.s.: 抱歉,第一篇帖子中忘记了一个 grep 选项


给我这个错误:"dd: invalid number `'". 顺便说一下,这是在一个测试文件上。我让它在一个9mb的文件上运行了几分钟,但没有完成。 - ilitirit
就像我说的那样,它非常慢。也许对你来说甚至更慢,因为grep没有正常工作。最好再试一次。 - ypnos

1
在PERL中,有一个内建的变量专门指向匹配正则表达式后面的字符串部分。那就是我会使用的方法。它不仅仅适用于Bash和实用工具,而且PERL安装得如此普遍,所以你应该没问题。

在Unix标准命令行中,大多数面向文本的实用工具处理二进制数据时表现不佳或不正确,因为它们会做出一些假设,例如在文件中没有'\0'字符。这就是为什么使用像Perl或Python这样没有这种限制的程序会更成功的原因。 - msw

0
 strings -n3 file_binary | awk '/XXX/{gsub(/.*XXX/,"");print}'

在我的系统上打印一个空白行。 - ilitirit
此输出会在下一个换行符处停止! - ypnos
1
awk '/XXX/{gsub(/.*XXX/,"");p=1}p{print}' - vladr

0
我想出了这个解决方案:
ls -1 *.bin | xargs strings -n4 --radix=d -f | grep "string" | awk '{sub(/:/, ""); print $2 " " $1 " " $1".";}' | xargs -l1 split -b && rm *.aa

ls -1 *.bin 以列表格式仅打印带有扩展名“bin”的文件名

xargs strings -n4 --radix=d -f 列出文件中的所有字符串及其位置,并在输出中包括文件名

grep "string" 打印包含“string”的行(每个文件中只出现一次)

awk '{sub(/:/, ""); print $2 " " $1 " " $1".";}' 移除由strings添加的文件名后面的冒号,并打印字符串的位置、文件名和带有句点的文件名(此行用作split命令的其余参数)

xargs -l1 split -b 对awk的输出进行逐行分割,使用split命令执行每一行

rm *.aa 删除分割文件的第一部分。“aa”是分割文件的默认后缀。

可能有更好/更快/更安全的方法来完成这个任务,但对于我的目的来说,这样做已经足够了。


0
你需要使用 stringsgrep 吗?
例如:
strings -n 3 myfilename | grep XXX

它只返回字符串,而不是其后面的位。我需要从字符串的开头到文件的结尾的所有内容。 - ilitirit

-1

试试这个:

grep -ao string.* filename

由于您有二进制数据,您可能想将输出重定向到文件。

grep -ao string.* filename > binary.out

或者通过 hexdump 或类似工具进行测试:

grep -ao string.* filename | hd

谢谢,但是当它遇到换行符时会失败。 - ilitirit
此输出会在下一个换行符处停止! - ypnos

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接