it-roy-ru.com

сценарии оболочки Linux: шестнадцатеричная строка в байтах

Допустим, у меня есть строка 5a. Это шестнадцатеричное представление ASCII Буквы Z. Мне нужно знать команду Linux Shell, которая будет принимать шестнадцатеричную строку И выводить двоичные байты, которые представляет строка.

Так что если я сделаю

echo 5a | command_im_looking_for > temp.txt

и я открываю temp.txt, я увижу одиночное письмо Z.

54
Krystian Cybulski
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'
57
bdonlan

Я делал это с помощью 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 не читает со стандартного ввода.

79
josch

Вы можете сделать это только через эхо и без других вещей. Не забудьте добавить «-n», иначе вы получите автоматический перевод строки:

echo -n -e "\x5a"
13
Fa11enAngel

Баш однострочный

echo -n "5a" | while read -N2 code; do printf "\x$code"; done
9
user3132194

в зависимости от того, где вы получили "5a", вы можете просто добавить\x к нему и перейти к printf 

$ a=5a
$ a="\x${a}"
$ printf "$a"
Z
3
ghostdog74

dC может конвертировать между числовыми базами:

$ echo 5a | (echo 16i; tr 'a-z' 'A-Z'; echo P) | dc
Z$
2
Roger Willcocks

Некоторые однострочники Python3, которые работают с любым количеством байтов.

Расшифровка hex (с strip, так что нормально иметь новую строку на stdin):

$ echo 666f6f0a | python3 -c "import sys, binascii; sys.stdout.buffer.write(binascii.unhexlify(input().strip()))"
foo

Кодировка шестнадцатеричная:

$ echo foo | python3 -c "import sys, binascii; print(binascii.hexlify(sys.stdin.buffer.read()).decode())"
666f6f0a
2
Jack O'Connor

Вот чистый скрипт bash (так как 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 уже запущен, это должно быть быстрее, чем любое другое решение, запускающее новый процесс.

1
Vouze
echo 5a | python -c "import sys; print chr(int(sys.stdin.read(),base=16))"
1
unutbu

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=
0
Steven Penny

В соответствии с @Randal comment , вы можете использовать Perl, например,.

$ printf 5a5a5a5a | Perl -lne 'print pack "H*", $_'
ZZZZ

и наоборот:

$ printf ZZZZ | Perl -lne 'print unpack "H*", $_'
5a5a5a5a

Еще один пример с файлом:

$ printf 5a5a5a5a | Perl -lne 'print pack "H*", $_' > file.bin
$ Perl -lne 'print unpack "H*", $_' < file.bin
5a5a5a5a
0
kenorb

Аналогично моему ответу здесь: Сценарии Linux Shell: шестнадцатеричное число в двоичной строке

Вы можете сделать это с помощью такого же инструмента, как этот (используя печатный символ ascii вместо 5a):

echo -n 616263 | cryptocli dd -decoders hex

Будет выдавать следующий результат:

abcd
0
tehmoon