1

У меня большой двоичный файл (несколько сотен гигабайт), и я хочу извлечь из него сегмент. Я знаю шестнадцатеричные строки начала и конца.

1 ответ1

2

Возможное решение (при условии, что вы можете сделать копию файла) может использовать следующий пример

  1. предположим, что стартовый паттерн шестнадцатеричный 4f 0f 87 82
  2. Предположим, что конец шаблона является шестнадцатеричным fb 8c e2 a0
  3. Предположим, что входной файл называется tf и имеет длину 5000 байт.

затем

сделать копию tf в новый файл, blah с измененным шаблоном запуска

$ LC_ALL=C sed 's/'`printf "\x4f\x0f\x87\x82"`'/'`printf "AAAA"`'/'  <tf > blah

теперь найдите место, где tf и blah различаются (примечание - sed записывает дополнительный байт, содержащий новую строку в конце измененного файла, поэтому мы сравниваем до длины исходного файла, tf .Сгенерированный файл blah должен быть на один байт длиннее).

$ cmp -n 5000 -b tf blah

это даст смещение байта, bs, где файлы различаются, например,

tf blah differ: byte 4337, line 10 is 117 O 101 A

Теперь сделайте то же самое для окончания шаблона

 $ LC_ALL=C sed  's/'`printf "\xfb\x8c\xe2\xa0"`'/'`printf "AAAA"`'/'  < tf > blah2
 $ cmp -n 5000 -b tf blah2
 tf blah2 differ: byte 4433, line 10 is 373 ? 101 A

теперь используйте dd для извлечения части интереса

dd if=tf skip=4336 bs=1 count=100 > fbit

Некоторые дополнительные заметки:

  1. некоторые версии sed поддерживают опцию -b которая обрабатывает входной файл как двоичный. В других версиях есть опция -z которая разделяет строки символами NUL. В любом случае сопоставление шаблонов, содержащих новую строку, или разбиение на новую строку не было проверено.

  2. count=100 будет зависеть от длины сопоставляемого шаблона и от того, должен ли соответствующий шаблон быть включен в извлечение (это не было ясно в вопросе). Общая формула: count = (конечное смещение) - (начальное смещение) + (размер конечного шаблона). Части для конкретного примера 4433-4337 + 1, что дает 97 байтов. То есть от начала начального шаблона до первого байта конечного шаблона включительно. Затем добавляются дополнительные 3 байта, чтобы получить 100 в этом примере, потому что последний шаблон имел четыре байта, и пример включает в себя последний шаблон. Если конечный шаблон не нужен, то значением будет count=96 .

  3. возможен подход, более устойчивый к новым строкам и использующий команду hexdump. Я не полностью проверил этот подход. Он по существу использовал бы hexdump с небольшим количеством sed, grep и tr, чтобы преобразовать оригинальный двоичный файл в шестнадцатеричный формат в виде ascii. Затем можно применить тот же процесс, но с более сложной арифметикой и т.д. Необходимая команда hexdump будет

    hexdump -v -x tf | sed s/'^[0-9]*\(.*\)/\1/' | sed s'/ *//g' | grep '[0-9]' | tr -d '\n' > tf.txt

  4. После hexdump шагу один и тот же процесс sed и cmp могут быть использованы. Соответствующий шаблон должен быть обновлен, чтобы использовать шестнадцатеричные символы ascii, а не исходную шестнадцатеричную печать.

  5. Этот подход должен также обрабатывать символы новой строки.

  6. LC_ALL=C , по-видимому, необходим в OSX по умолчанию. Без этого команда sed выдает ошибку RE error: illegal byte sequence . Это может быть не так на всех платформах и / или дистрибутивах ОС.

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .