Замена двоичного кода

Я пытался сделать замену sed в двоичном файле, однако я начинаю считать, что это невозможно. По сути, я хотел сделать следующее:

sed -bi "s/\(\xFF\xD8[[:xdigit:]]\{1,\}\xFF\xD9\)/\1/" file.jpg

Логика, которую я хочу достичь, заключается в следующем: просканировать двоичный файл до шестнадцатеричного кода FFD8, продолжить чтение до FFD9 и сохранить только то, что было между ними (отбрасывает мусор до и после, но включает FFD8 и FFD9 в качестве сохраненной части файла)

Есть ли хороший способ сделать это? Даже если вы не используете sed?

EDIT: Я просто играл и нашел самый чистый способ сделать это IMO. Я знаю, что это выражение grep будет жадным.

hexdump -ve '1/1 "%.2x"' dirty.jpg | grep -o "ffd8.*ffd9" | xxd -r -p > clean.jpg

Ответ 1

bbe является "sed для двоичных файлов" и должен работать более эффективно для больших двоичных файлов, чем hexdumping/restore.

Пример использования:

$ bbe -e 's/original/replaced/' infile > outfile

Дополнительная информация на странице .

Ответ 2

Is there a good way to do this

да, конечно, используйте инструмент редактирования изображений, например, инструмент ImageMagick (поиск в сети для linux jpeg, exif editor и т.д.), который знает, как редактировать метаданные jpg. Я уверен, что вы найдете один инструмент, который вам подходит. Не пытайтесь делать это с трудом.:)

Ответ 3

sed может это сделать, но это может быть сложно. Здесь Python script делает то же самое (обратите внимание, что он редактирует файл на месте, что я предполагаю, что вы хотите сделать на основе вашего sed script):

import re

f = open('file.jpeg', 'rb+')
data = f.read()
match = re.search('(\xff\xd8[0-9A-fa-f]+)\xff\xd9', data)
if match:
    result = match.group(1)
    f.seek(0)
    f.write(result)
    f.truncate()
else:
    print 'No match'
f.close()

Ответ 4

Кроме того, этот Perl может работать (не проверен, caveat emptor)... если Python не установлен:)

open(FILE, "file.jpg") || die "no open $!\n";
while (read(FILE, $buff, 8 * 2**10)) {
    $content .= $buff;
}
@matches = ($content =~ /(\xFF\xD8[:xdigit:]+?\xFF\xD9)/g;
print STDOUT join("", @matches);

Вам нужно добавить binmode(FILE); binmode(STDOUT); в DOS или VMS после вызова open() - не требуется в Unix.