在awk程序中,我调用一些产生一组二进制字符串的命令,它们一起运行。
在每个字符串中:
如果类型代码是0x20,我想将其更改为0x1E。
示例:
第一个字符串的前几个字节是:
4a d8 64 54 13 01 00 00 00 2d 00 00 00
从偏移量0x04开始,我们看到类型代码是0x13,所以什么都不做。
从偏移量0x09开始,我们看到长度为2d 00 00 00.远离此字符串的开头,找到下一个字符串的开头。
下一个字符串开始:
4a d8 64 54 20 01 00 00 00 2c 00 00 00
从偏移量0x04开始,我们看到类型代码是0x20。将其更改为0x1E。
从偏移量0x09开始,我们看到长度为2c 00 00 00.远离此字符串的开头,找到下一个字符串(或EOF)的开头。
最适用于此的实用程序是什么?
答案 0 :(得分:2)
我在perl中实施了一个解决方案。我假设大小不包括13字节头。它没有完全成熟,但有效。它是一种工作台模型。它在内存中创建一些数据,然后进行修改。
所以第一部分只是根据标题创建内存数据:
#!/usr/bin/perl
use strict;
use warnings;
# Glues binary strings -> not needed $a.$b works properly
#sub glue(@) { pack "W*", map { unpack("W*", $_) } @_; }
# Creates a <header:null data> record
sub pck(@) {
my $h = pack "(H[2])*", @_;
# If it is big-endian use N instead of V!!!
# It has to be unpacked to get the 32 bit data size
my @u = unpack "C5V2", $h;
my $b = pack "x$u[6]"; # put a lot of NULL bytes
$h.$b;
}
my @h1=qw(4a d8 64 54 13 01 00 00 00 2d 00 00 00);
my @h2=qw(4a d8 64 54 20 01 00 00 00 2c 00 00 00);
my $d1 = pck @h1;
my $d2 = pck @h2;
my $d = $d1.$d2;
现在$d
包含两条记录:<header1><zero data1><header2><zero data2>
。现在我们可以转储数据了:
sub dumpbin(@) {
open my $fh, "|od -t x1" or die;
binmode $fh;
print $fh @_;
close $fh;
}
dumpbin($d);
输出:
0000000 4a d8 64 54 13 01 00 00 00 2d 00 00 00 00 00 00
0000020 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
*
0000060 00 00 00 00 00 00 00 00 00 00 4a d8 64 54 20 01
0000100 00 00 00 2c 00 00 00 00 00 00 00 00 00 00 00 00
0000120 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
*
0000160 00 00 00
0000163
现在,如果需要,可以解析和修改内存中数据。标头被转储。偏移量以八进制打印,以符合od
的输出。
print "=====\n";
for (my $offs=0; $offs<length($d);) {
# Unpack header
my @h = unpack "C5V2", substr($d, $offs, 13);
# Checks if the header type is 0x20 and modifies it
if ($h[4] eq 0x20) { substr($d, $offs + 4, 1) = pack "W", 0x1e;}
printf "%07o HDR: %s%s\n", $offs, join(" ", map {sprintf "%x", $_} @h),
$h[4] eq 0x20 ? " *" : "";
$offs += 13 + $h[6];
}
print "=====\n";
输出:(修改后的行标有&#39; *&#39;)
=====
0000000 HDR: 4a d8 64 54 13 1 2d
0000072 HDR: 4a d8 64 54 20 1 2c *
=====
如果我们转储结果,可以看到数据已正确更改:
dumpbin($d);
输出:
0000000 4a d8 64 54 13 01 00 00 00 2d 00 00 00 00 00 00
0000020 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
*
0000060 00 00 00 00 00 00 00 00 00 00 4a d8 64 54 1e 01
0000100 00 00 00 2c 00 00 00 00 00 00 00 00 00 00 00 00
0000120 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
*
0000160 00 00 00
0000163
可以看出数据已被修改。
如果输入文件很大,则需要更多代码来读取块中的数据,修改和回写。
我希望这有帮助!