Linux shell scripting: hex string to bytes
Предположим, что у меня есть строка 5a
. Это шестнадцатеричное представление ASCII
письмо Z. Мне нужно знать команду оболочки Linux, которая возьмет шестую строку
и вывести двоичные байты, которые представляет строка.
Итак, если я делаю
echo 5a | command_im_looking_for > temp.txt
и я открываю temp.txt
, я увижу одиночную букву Z.
Ответы
Ответ 1
echo -n 5a | perl -pe 's/([0-9a-f]{2})/chr hex $1/gie'
Обратите внимание, что это не будет пропускать шестнадцатеричные символы. Если вам нужен только шестнадцатеричный (без пробелов от исходной строки и т.д.):
echo 5a | perl -ne 's/([0-9a-f]{2})/print chr hex $1/gie'
Кроме того, zsh
и bash
поддерживают это изначально в echo
:
echo -e '\x5a'
Ответ 2
Я использовал это, используя xxd
echo -n 5a | xxd -r -p
Но потом я понял, что в Debian/Ubuntu xxd является частью vim-common и, следовательно, может отсутствовать в минимальной системе. Чтобы избежать perl (imho также не является частью минимальной системы), я закончил использование sed, xargs и printf следующим образом:
echo -n 5a | sed 's/\([0-9A-F]\{2\}\)/\\\\\\x\1/gI' | xargs printf
В основном я хочу только преобразовать несколько байтов, и это хорошо для таких задач. Преимущество этого решения над одним из ghostdog74 заключается в том, что он может автоматически преобразовывать шестнадцатеричные строки произвольной длины. xargs используется, потому что printf не читает со стандартного ввода.
Ответ 3
Вы можете сделать это только через эхо и без других вещей. Не забудьте добавить "-n", или вы получите автоматическую линию:
echo -n -e "\x5a"
Ответ 4
Bash однострочный
echo -n "5a" | while read -N2 code; do printf "\x$code"; done
Ответ 5
в зависимости от того, где вы получили этот "5a", вы можете просто добавить \x к нему и перейти к printf
$ a=5a
$ a="\x${a}"
$ printf "$a"
Z
Ответ 6
Некоторые однострочные python3, которые работают с любым количеством байтов.
Декодирование hex (с strip
, так что это нормально иметь новую строку на stdin):
$ echo 666f6f0a | python3 -c "import sys, binascii; sys.stdout.buffer.write(binascii.unhexlify(input().strip()))"
foo
Кодирование hex:
$ echo foo | python3 -c "import sys, binascii; print(binascii.hexlify(sys.stdin.buffer.read()).decode())"
666f6f0a
Ответ 7
echo 5a | python -c "import sys; print chr(int(sys.stdin.read(),base=16))"
Ответ 8
Вот чистый bash script (поскольку printf является встроенным bash):
#warning : spaces do matter
die(){ echo "[email protected]" >&2;exit 1;}
p=48656c6c6f0a
test $((${#p} & 1)) == 0 || die "length is odd"
p2=''; for ((i=0; i<${#p}; i+=2));do p2=$p2\\x${p:$i:2};done
printf "$p2"
Если bash уже запущен, это должно быть быстрее любого другого решения, запускающего новый процесс.
Ответ 9
dc может преобразовывать числовые базы:
$ echo 5a | (echo 16i; tr 'a-z' 'A-Z'; echo P) | dc
Z$
Ответ 10
GNU awk 4.1
awk -niord '$0=chr("0x"RT)' RS=.. ORS=
Обратите внимание, что если вы эхо к этому, он выдает дополнительный нулевой байт
$ echo 595a | awk -niord '$0=chr("0x"RT)' RS=.. ORS= | od -tx1c
0000000 59 5a 00
Y Z \0
Вместо этого используйте printf
$ printf 595a | awk -niord '$0=chr("0x"RT)' RS=.. ORS= | od -tx1c
0000000 59 5a
Y Z
Также обратите внимание, что GNU awk создает UTF-8 по умолчанию
$ printf a1 | awk -niord '$0=chr("0x"RT)' RS=.. ORS= | od -tx1
0000000 c2 a1
Если вы имеете дело с символами вне ASCII, и вы собираетесь
Base64, кодирующий результирующую строку, вы можете отключить UTF-8 с помощью -b
echo 5a | sha256sum | awk -bniord 'RT~/\w/,$0=chr("0x"RT)' RS=.. ORS=
Ответ 11
Как и в моем ответе: Сценарии оболочки Linux: шестнадцатеричное число до двоичной строки
Вы можете сделать это с помощью того же инструмента, подобного этому (используя символ ascii для печати вместо 5a
):
echo -n 616263 | cryptocli dd -decoders hex
Произведет следующий результат:
abcd
Ответ 12
od -c
или
hexdump -c