我正在尝试从ANSI字符串“stringstart”和“stringend”之间的二进制文件中删除部分。是否可以使用sed或perl -pe执行此操作?
我正在考虑一些正则表达式解决方案,但我不知道如何编写它或正则表达式如何与二进制文件一起使用。
答案 0 :(得分:6)
sed
旨在处理文本文件而不是二进制文件,尽管如今,这种区别通常不如以前那么重要。最大的问题是文本文件不包含零字节(值为0的字节)和二进制文件,并且许多C字符串处理函数在第一个零字节处停止。 sed
还会读取由换行符标记的“行”。因此,二进制文件最终可能会出现长行。最后,无法保证字符串开始和结束标记相对于换行符的相对位置。所有这些特征使得sed
不太适合这项工作,而不是Perl。
在Perl中,我非常想把文件篡改到内存中,使用适当的正则表达式从内存映像中删除数据,然后将结果写回适当的位置。
perl -e 'local($/); $data = <>; $data =~ s/stringstart(.*?)stringend//gms; print $data'
现已测试 - 使用以下方法创建测试数据:
#!/usr/bin/env perl
use strict;
use warnings;
sub full_set
{
foreach my $i (0..255) { printf "%c", $i; }
}
sub random_set
{
my($n) = @_;
foreach my $i (0..$n) { printf "%c", int(rand(255)); }
}
full_set;
random_set(1024);
printf("stringstart");
full_set;
random_set(512);
full_set;
printf("stringend");
random_set(256);
脚本从输入中删除1045个字符 - 对应于'stringstart','stringend'(20)+ 2 * 256 + 513(因为random_set(512)
打印513个字符)。
请注意,主脚本会立即将所有文件读入内存。如果你希望它一次处理一个文件,你将不得不更努力地工作;它可能不再是单行。
答案 1 :(得分:2)
另一种方法:
perl -pi -we'BEGIN{$/="stringend"} chomp and s/stringstart.*//s' your_binary_file
答案 2 :(得分:0)
您可以使用正则表达式来杀死 [] 中 ^ 之后未定义的所有字符。例如
cp /bin/ls ./binfile
file binfile
binfile: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.18, stripped
在它上面做perl派:
perl -pi -e 's/[^[a-zA-Z0-9_+\n]//g' binfile
然后再查看二进制文件:
file binfile
binfile: ASCII text, with very long lines
你显然必须为该命令添加更多内容,因为它将删除其他几个可能有效的字符。但这应该让你开始。