В настоящее время я работаю над некоторыми двоичными данными.
Для проверки и отладки данных, ранее созданных моим приложением, я использую шестнадцатеричного, лицом к препятствию hexdump не представляется возможным извлечь 64-битное целочисленное поле.
Приведен следующий минимальный пример:
#include <iostream>
#include <fstream>
#include <cstdint>
int main(int argc, char** argv){
std::ofstream os("tmp.bin", std::ios::out | std::ios::binary);
uint64_t x = 7;
os.write((char*)&x,sizeof(uint64_t));
os.close();
return 0;
}
Я выполняю простой hexdump в моей системе:
hexdump tmp.bin
> 0000000: 0007 0000 0000 0000
> 0000008:
Теперь попробуем извлечь целое число без знака 64-битной ширины:
hexdump -e '/8 "%u"' tmp.bin
> hexdump: bad byte count for conversion character u
По хорошо написанному hexdump-руководство по Дэвид Мэйр это должно быть возможно, но у меня нет успеха.
Что мне не хватает?
Наш последний обходной путь выглядит следующим образом:
x=`hexdump -n 8 -e '2/4 "%08X " "\n"' {FILENAME} | awk 'BEGIN{printf "0x"}{print $2$1}'`
echo $(($x))
Пояснения к каждой части:
Извлечь восемь байтов 64-битного целочисленного значения из файла {FILENAME}
в виде двух четырехбайтовых фрагментов, напечатанных в виде шестнадцатеричных кодированных значений.
hexdump -n 8 -e '2/4 "%08X " "\n"' {FILENAME}
Инвертирует порядок байтов двух блоков и печатает их как один блок из восьми байтов, представляющий двоичное значение. Prepend 0x для последующей обработки.
awk 'BEGIN{printf "0x"}{print $2$1}
Сохраните шестнадцатеричное представление в x для оценки bash.
x=`....`
Пусть оболочка bourne интерпретирует и выводит шестнадцатеричное закодированное значение 64-битной целочисленной переменной (здесь предварительно добавленный 0x нужно).
echo $(($x))
Можно также использовать sed. Следующее соответствует 8-байтовым шестнадцатеричным целым числам и заменяет их. Опять же, это работает только для целых чисел без знака.
hexdump ... | sed 's/0x\([0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f]\)\([0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f]\)/0x\2\1/'
AFAICT нужно уметь писать гораздо понятнее
hexdump ... | sed 's/0x\([0-9a-f]{8,8}\)\([0-9a-f]{8,8}\)/0x\2\1/'
обычно с некоторым параметром командной строки, таким как -E, чтобы включить расширенные регулярные выражения, но по крайней мере в Mac OS X 10.10 это не работает.