Преобразование двоичных данных в шестнадцатеричный в сценарии оболочки

Я хочу преобразовать двоичные данные в шестнадцатеричные, просто так, без причудливого форматирования и всего остального. hexdump кажется слишком умным, и для меня он "переформатирует". Я хочу взять x байтов из /dev/random и передать их в шестнадцатеричном виде.

Предпочтительно я хотел бы использовать только стандартные инструменты Linux, чтобы мне не нужно было устанавливать их на каждую машину (их много).


person davka    schedule 09.06.2011    source источник
comment
Мне пришлось использовать /dev/urandom, /dev/random просто завис   -  person Aquarius Power    schedule 12.04.2015
comment
Случайные блоки @AquariusPower, когда у него недостаточно случайных данных, а urandom - нет (IIRC перебирает то, что у него есть)   -  person davka    schedule 20.05.2015


Ответы (8)


Возможно, используйте xxd:

% xxd -l 16 -p /dev/random
193f6c54814f0576bc27d51ab39081dc
person unutbu    schedule 09.06.2011
comment
xxd является частью vim, поэтому он не всегда может быть установлен. - person Håkon A. Hjortland; 25.07.2012
comment
Обратите внимание, что вы можете использовать -c для изменения количества байтов в строке. К сожалению, вы можете установить его только на 256, после чего вам нужно добавить несколько новых строк. - person Kevin Cox; 12.11.2013
comment
Я просто хотел поблагодарить вас и сказать, что это самый быстрый способ генерировать данные без выполнения чрезмерной работы. я буквально сделал 2-гигабайтный файл за несколько секунд, мне нужны были 32-байтовые строки в шестнадцатеричном формате, и это помогло time xxd -c 32 -l 1024000000 -ps /dev/urandom 32bytehexnewtest1.txt ; real 0m17.484s - person cigol on; 08.10.2020

Осторожно!

hexdump и xxd дают результаты с другим порядком байтов!

$ echo -n $'\x12\x34' | xxd -p
1234
$ echo -n $'\x12\x34' | hexdump -e '"%x"'
3412

Объясняется просто. Прямой порядок байтов против прямого байта :D

person Zibri    schedule 16.01.2012
comment
Используйте echo -n $'\x12\x34' | hexdump -e '/1 "%x"', чтобы получить тот же порядок следования байтов. - person ; 16.11.2015
comment
Также будьте осторожны! hexdump удалит ведущие нули. - person Edward Ned Harvey; 24.06.2018

С od (системы GNU):

$ echo abc | od -A n -v -t x1 | tr -d ' \n'
6162630a

С помощью hexdump (BSD):

$ echo abc | hexdump -ve '/1 "%02x"'
6162630a

Из шестнадцатеричный дамп, od и шестнадцатеричный дамп:

В зависимости от типа вашей системы будут доступны одна или обе из этих двух утилит: системы BSD не рекомендуют использовать od для шестнадцатеричного дампа, а системы GNU — наоборот.

person Håkon A. Hjortland    schedule 24.07.2012
comment
Спустя 4 года (не так много, я знаю), чаще всего я читаю ветку о *nix, узнаю что-то действительно старое и все же совершенно новое для меня. +1 за од, никогда о нем не слышал, очень полезно и присутствует даже на Cygwin. ;-) - person Charles Roberto Canato; 07.09.2013

Возможно, вы могли бы написать свой собственный небольшой инструмент на C и скомпилировать его на лету:

int main (void) {
  unsigned char data[1024];
  size_t numread, i;

  while ((numread = read(0, data, 1024)) > 0) {
    for (i = 0; i < numread; i++) {
      printf("%02x ", data[i]);
    }
  }

  return 0;
}

А затем подайте его со стандартного ввода:

cat /bin/ls | ./a.out

Вы даже можете встроить эту небольшую программу на C в сценарий оболочки, используя синтаксис heredoc.

person Blagovest Buyukliev    schedule 09.06.2011
comment
С, для этого? Это перебор. - person ; 09.06.2011
comment
Ну, зато у вас есть полный контроль над форматированием и поведением :-) - person Blagovest Buyukliev; 09.06.2011
comment
это всегда вариант, но я был совершенно уверен, что это было решено раньше :) - person davka; 09.06.2011
comment
@ user405725 - кажется, это самое простое решение для программиста на C. Насколько я могу судить, все остальные решения не шестнадцатерично кодируют двоичный файл. Я озадачен тем, насколько сложной стала эта задача. Неужели так чертовски сложно закодировать двоичный файл в шестнадцатеричном формате? - person jww; 05.10.2017
comment
Невероятно, но это вполне может быть лучшим ответом на этот вопрос. - person mnistic; 05.03.2018

Все решения кажутся трудными для запоминания или слишком сложными. Я нахожу использование printf самым коротким:

$ printf '%x\n' 256
100

Но, как отмечено в комментариях, это не то, чего хочет автор, поэтому, честно говоря, ниже приведен полный ответ.

... использовать выше для вывода фактического потока двоичных данных:

printf '%x\n' $(cat /dev/urandom | head -c 5 | od -An -vtu1)

Что оно делает:

  • printf '%x\n' .... - печатает последовательность целых чисел, т.е. printf '%x,' 1 2 3, будет печатать 1,2,3,
  • $(...) - это способ получить вывод некоторой команды оболочки и обработать его.
  • cat /dev/urandom - выводит случайные бинарные данные
  • head -c 5 - ограничивает двоичные данные до 5 байт
  • od -An -vtu1 - команда восьмеричного дампа, преобразует двоичный код в десятичный

В качестве тестового примера («a» - 61 шестнадцатеричный, «p» - 70 шестнадцатеричный,...):

$ printf '%x\n' $(echo "apple" | head -c 5 | od -An -vtu1)
61
70
70
6c
65

Или, чтобы проверить отдельные двоичные байты, на входе давайте 61 десятичное число ('=' char) для получения двоичных данных (формат '\\x%x' делает это). Приведенная выше команда правильно выведет 3d (десятичное число 61):

$printf '%x\n' $(echo -ne "$(printf '\\x%x' 61)" | head -c 5 | od -An -vtu1)
3d
person marcinj    schedule 04.10.2016
comment
@МалъСкрылевъ Я обновил свой ответ, вы правы, я упустил основной вопрос - я, вероятно, искал самый простой способ преобразования десятичного числа в шестнадцатеричное в оболочке, и этот ответ отображается в Google первым. - person marcinj; 27.08.2017
comment
эй, я знаю, что это старо, но для второго блока кода вы не могли бы просто пропустить кошку и просто сделать голову напрямую? printf '%x\n' $(head -c 5 /dev/urandom | od -An -vtu1) или есть конкретная причина для команды cat? Кроме того, если вы хотите, чтобы шестнадцатеричный код был разделен только новой строкой в ​​​​конце, я придумал это echo $(printf "%x" $(head -c 5 /dev/urandom | od -An -vtu1)), хотя я не знаю затрат на производительность для них и, в основном, почему я спрашиваю об вырезании команды cat. Я новичок в командной строке, но эта информация помогает. - person cigol on; 08.10.2020
comment
Голова @cigolon лучше кошки. Я часто использую команду time для измерения производительности команд. - person marcinj; 10.10.2020
comment
вот почему я спросил об этом. printf '%x\n' $(cat /dev/urandom | head -c 5 | od -An -vtu1) VS printf '%x\n' $(head -c 5 /dev/urandom | od -An -vtu1) вторая команда без кошачьей трубы в целом немного быстрее. - person cigol on; 24.02.2021

Если вам нужен большой поток (без новой строки), вы можете использовать tr и xxd (часть Vim) для побайтового преобразования.

head -c1024 /dev/urandom | xxd -p | tr -d $'\n'

Или вы можете использовать hexdump (POSIX) для пословного преобразования.

head -c1024 /dev/urandom | hexdump '-e"%x"'

Обратите внимание, что разница заключается в порядке следования байтов.

person Kevin Cox    schedule 12.11.2013
comment
Используйте echo abc | hexdump -e '/1 "%02x"' для получения сетевого порядка и 0 для 0x0a. - person ; 16.11.2015

dd + hexdump также будет работать:

dd bs=1 count=1 if=/dev/urandom 2>/dev/null  | hexdump -e '"%x"'
person Community    schedule 09.06.2011
comment
спасибо, я начал так, но не смог заставить hexdump делать то, что я хочу. Я был совершенно уверен, что у него есть нужная мне опция, но не смог найти ее на странице руководства. - person davka; 09.06.2011
comment
С этим решением (hexdump -e '%x'): '\n' -> 'a' (отсутствует начальный "0"), 'abcde' -> '6463626165' (неправильный порядок байтов). Это может быть очень плохо в приложениях с неслучайными данными! - person Håkon A. Hjortland; 25.07.2012

Эти три команды будут печатать одно и то же (0102030405060708090a0b0c):

n=12
echo "$a" | xxd -l "$n" -p
echo "$a" | od  -N "$n" -An -tx1 | tr -d " \n" ; echo
echo "$a" | hexdump -n "$n" -e '/1 "%02x"'; echo

Учитывая, что n=12 и $a - это значения байтов от 1 до 26:

a="$(printf '%b' "$(printf '\\0%o' {1..26})")"

Это можно использовать для получения $n случайных значений байтов в каждой программе:

xxd -l "$n" -p                   /dev/urandom
od  -vN "$n" -An -tx1            /dev/urandom | tr -d " \n" ; echo
hexdump -vn "$n" -e '/1 "%02x"'  /dev/urandom ; echo
person Community    schedule 16.11.2015