Replacing 1500 bytes at a variable offset

A

A. Farber

How could I replace 1500 bytes in a file, please?
They are not located at some fixed offset and also
the amount of replacing bytes could be bigger or
smaller than 1500. Here's what I am trying currently:

my $SEARCH = pack 'C*', map { hex } qw(
98 e6 52 ca db ce db 19 62 00 00 00
69 b5 40 0c 91 dc 6b 43 cf 00 00 00
5b 7d 92 c2 e1 ec f1 45 11 00 00 00
92 45 a3 64 0b ff e4 d9 a6 00 00 00
2e 0d cb 22 50 0e 92 5a 0f 00 00 00
4e d5 78 59 ee 1c 8b c6 cc 00 00 00
.... );

my $REPLACE = pack 'C*', map { hex } qw(
ff ff ff ff ff ff ff ff ff ff ff ff
69 b5 40 0c 91 dc 6b 43 cf 00 00 00
5b 7d 92 c2 e1 ec f1 45 11 00 00 00
92 45 a3 64 0b ff e4 d9 a6 00 00 00
2e 0d cb 22 50 0e 92 5a 0f 00 00 00
.... );

use constant KEYSIZE => length $SEARCH;

while (sysread $upload, $chunk, KEYSIZE) {
$both = $prev . $chunk;
if ($both =~ s/$SEARCH/$REPLACE/o) {
die "syswrite failed: $!"
unless length $both == syswrite $fh, $both;
undef $prev;
} else {
die "syswrite failed: $!"
unless length $prev == syswrite $fh, $prev;
$prev = $chunk;
}
}
# don't forget to print the last line
die "syswrite failed: $!"
unless length $prev == syswrite $fh, $prev;

Unfortunately the regex doesn't compile, probably
because it doesn't like the binary data I feed to it!

Regards
Alex
 
J

John W. Krahn

A. Farber said:
How could I replace 1500 bytes in a file, please?
They are not located at some fixed offset and also
the amount of replacing bytes could be bigger or
smaller than 1500. Here's what I am trying currently:

my $SEARCH = pack 'C*', map { hex } qw(
98 e6 52 ca db ce db 19 62 00 00 00
69 b5 40 0c 91 dc 6b 43 cf 00 00 00
5b 7d 92 c2 e1 ec f1 45 11 00 00 00
92 45 a3 64 0b ff e4 d9 a6 00 00 00
2e 0d cb 22 50 0e 92 5a 0f 00 00 00
4e d5 78 59 ee 1c 8b c6 cc 00 00 00
.... );

my $REPLACE = pack 'C*', map { hex } qw(
ff ff ff ff ff ff ff ff ff ff ff ff
69 b5 40 0c 91 dc 6b 43 cf 00 00 00
5b 7d 92 c2 e1 ec f1 45 11 00 00 00
92 45 a3 64 0b ff e4 d9 a6 00 00 00
2e 0d cb 22 50 0e 92 5a 0f 00 00 00
.... );

use constant KEYSIZE => length $SEARCH;

while (sysread $upload, $chunk, KEYSIZE) {
$both = $prev . $chunk;
if ($both =~ s/$SEARCH/$REPLACE/o) {
die "syswrite failed: $!"
unless length $both == syswrite $fh, $both;
undef $prev;
} else {
die "syswrite failed: $!"
unless length $prev == syswrite $fh, $prev;
$prev = $chunk;
}
}
# don't forget to print the last line
die "syswrite failed: $!"
unless length $prev == syswrite $fh, $prev;

Unfortunately the regex doesn't compile, probably
because it doesn't like the binary data I feed to it!

It is not that the data is binary, it is because some of the characters
are special to regular expressions. Use the quotemeta escape to fix it.

s/\Q$SEARCH/$REPLACE/o


John
 
A

Anno Siegel

To the OP:
Uh... Did you test this part? "use constant" happens at compile time,
the assignment to $SEARCH happens later at run time. That would make
KEYSIZE 0 and issue a warning.

Make SEARCH and REPLACE constants too, that would also justify the
caps.
It is not that the data is binary, it is because some of the characters
are special to regular expressions. Use the quotemeta escape to fix it.

s/\Q$SEARCH/$REPLACE/o

That should do it, but with a fixed binary string that size I'd prefer
an index/substr based solution over s///. Something like (untested)

$_ >= 0 and substr( $both, $_, KEYSIZE) = REPLACE for index $both, SEARCH;

Anno
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,770
Messages
2,569,584
Members
45,075
Latest member
MakersCBDBloodSupport

Latest Threads

Top