你可以使用sed或perl -pe从二进制文件中删除一个部分吗?

时间:2011-06-26 17:07:19

标签: regex perl sed replace

我正在尝试从ANSI字符串“stringstart”和“stringend”之间的二进制文件中删除部分。是否可以使用sed或perl -pe执行此操作?

我正在考虑一些正则表达式解决方案,但我不知道如何编写它或正则表达式如何与二进制文件一起使用。

3 个答案:

答案 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

你显然必须为该命令添加更多内容,因为它将删除其他几个可能有效的字符。但这应该让你开始。