У меня большой двоичный файл (несколько сотен гигабайт), и я хочу извлечь из него сегмент. Я знаю шестнадцатеричные строки начала и конца.
1 ответ
Возможное решение (при условии, что вы можете сделать копию файла) может использовать следующий пример
- предположим, что стартовый паттерн шестнадцатеричный 4f 0f 87 82
- Предположим, что конец шаблона является шестнадцатеричным fb 8c e2 a0
- Предположим, что входной файл называется
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
Некоторые дополнительные заметки:
некоторые версии sed поддерживают опцию
-b
которая обрабатывает входной файл как двоичный. В других версиях есть опция-z
которая разделяет строки символами NUL. В любом случае сопоставление шаблонов, содержащих новую строку, или разбиение на новую строку не было проверено.count=100
будет зависеть от длины сопоставляемого шаблона и от того, должен ли соответствующий шаблон быть включен в извлечение (это не было ясно в вопросе). Общая формула: count = (конечное смещение) - (начальное смещение) + (размер конечного шаблона). Части для конкретного примера 4433-4337 + 1, что дает 97 байтов. То есть от начала начального шаблона до первого байта конечного шаблона включительно. Затем добавляются дополнительные 3 байта, чтобы получить 100 в этом примере, потому что последний шаблон имел четыре байта, и пример включает в себя последний шаблон. Если конечный шаблон не нужен, то значением будетcount=96
.возможен подход, более устойчивый к новым строкам и использующий команду 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
После
hexdump
шагу один и тот же процессsed
иcmp
могут быть использованы. Соответствующий шаблон должен быть обновлен, чтобы использовать шестнадцатеричные символы ascii, а не исходную шестнадцатеричную печать.Этот подход должен также обрабатывать символы новой строки.
LC_ALL=C
, по-видимому, необходим в OSX по умолчанию. Без этого командаsed
выдает ошибкуRE error: illegal byte sequence
. Это может быть не так на всех платформах и / или дистрибутивах ОС.