Двоичные к шестнадцатеричным и десятичным в сценарии оболочки

20

У меня есть контекст, где мне нужно преобразовать двоичные в шестнадцатеричные и десятичные и наоборот в сценарии оболочки. Может кто-нибудь предложить мне инструмент для этого?

Банги
источник
7
Видя недавние ответы, возможно, вам следует указать, означает ли «двоичное» двоичное число или двоичный файл .
manatwork
1
возможный межсайтовый дубликат: stackoverflow.com/questions/13280131/… и stackoverflow.com/questions/378829/…
Сиро Сантилли 改造 改造 中心 法轮功 六四 事件

Ответы:

39

Это довольно просто сделать преобразование из двоичного в чистом Bash ( echoи printfявляются встроенными):

Двоичный в десятичный

$ echo "$((2#101010101))"
341

Двоичный в шестнадцатеричный

$ printf '%x\n' "$((2#101010101))"
155

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

Крис Даун
источник
как насчет десятичного до шестнадцатеричного.
Банги
2
@ Банги Просто сделай printf '%x\n' 10, например.
Крис Даун
1
Какой смысл использовать printf %dдля bin2dec? $(( ... ))уже дает десятичный результат, echoдостаточно.
Андреа Корбеллини
@AndreaCorbellini - Личные предпочтения. В общем, я использую printf '%s\n' fooвместо echoмножества причин (в основном, переносимость), по той же причине, я здесь не использую.
Крис Даун
@ChrisDown: я думал, что этот вопрос был явно о Bash (который имеет хорошо реализованную echoвстроенную функцию ). Виноват!
Андреа Корбеллини
16

Предполагая, что под двоичными данными вы подразумеваете двоичные данные как в данных с любым возможным байтовым значением, включая 0, а не числа с базовыми 2:

Для преобразования из двоичного файла, od(стандарт), xxd(поставляется с vim) или perl«s unpackприходит на ум.

od -An -vtu1 # for decimal
od -An -vtx1 # for hexadecimal

xxd -p # for hexa

perl -pe 'BEGIN{$\="\n";$/=\30};$_=unpack("H*",$_)' # like xxd -p

# for decimal:
perl -ne 'BEGIN{$\="\n";$/=\30;$,=" "}; print unpack("C*",$_)'

Теперь, чтобы преобразовать обратно в двоичный файл awk(стандартный) xxd -rили perls pack:

Из десятичной дроби от od -tu1или perlвыше:

LC_ALL=C awk '{for (i = 1; i <= NF; i++) printf "%c", $i}'
perl -ape '$_=pack("C*",@F)'

Из гекса perlили xxd -pвыше:

xxd -r -p
perl -pe 'chomp;$_=pack("H*",$_)'
Стефан Шазелас
источник
13

Вы можете использовать бв для этого, манипулируя ibaseи obaseпараметры:

Хитрость в том, что вам нужно четко указывать основы. Так что если ваш ibase равен 2, то если вы установите свой obase на 10, он ничего не сделает, так как 10 в двоичном виде - 2. Следовательно, вам нужно использовать шестнадцатеричное представление.

Таким образом, двоичное в десятичное будет (смотреть, что obase это A)

Двоичные в десятичные:

$> echo 'ibase=2;obase=A;11110001011010'|bc
15450

Бинарный в гекс:

$> echo 'ibase=2;obase=10000;11110001011010'|bc
3C5A

Если obaseсначала изменить «выходную базу» , это должно быть проще:

$> echo 'obase=10;ibase=2;11110001011010'|bc
15450
$> echo 'obase=16;ibase=2;11110001011010'|bc
3C5A
psarossy
источник
6
Этот второй пример неверен - «F» будет основанием 15, а не 16 (десятичное число 16 в шестнадцатеричном виде равно 10, а не F). Попробуйте, echo 'ibase=2;obase=F;1111который должен быть равен десятичной 15, т.е. F в гекс. Получается как 10, что в базе 15 (цифры 0-E). Кроме того , легче , если вы указать obase первой , например: echo 'obase=16;ibase=2;1111'|bc. Нет путаницы.
Златовласка
2
Теперь это худшее. После того, как вы установите ibase, вы должны предоставить вход в эту базу, даже для obase. Так в вашем примере будет echo 'ibase=2;obase=10000;11110001011010'|bc. Лучше прислушайтесь к совету Златовласки и измените порядок - сначала установите obase, а затем ibase.
manatwork
3

Если вы имеете в виду преобразование чисел из базы-2 в 10 или 16 и обратно, bcэто стандартный инструмент для этого, как уже упоминалось в psarossy .

decimal=123
binary=$(echo "obase=2;$decimal" | bc)
hex=$(echo "obase=16;ibase=2;$binary" | bc)

В некоторых оболочках zshесть встроенная поддержка преобразования базы как часть их арифметических операторов расширения:

decimal=123
binary=$(([##2]decimal))
hex=$(([##16]decimal))
hex=$(([##16]2#$binary))
decimal=$((2#$binary))

и так далее.

Оба, ksh93а zshтакже поддержка:

typeset -i2 binary=123
typeset -i16 dec2hex=123 bin2hex='2#1111'

Но обратите внимание, что при расширении $binaryбудет иметь префикс 2#или 16#(который можно удалить с помощью ${binary#*#}.

ksh93 также поддерживает:

printf "%..2d\n" 123

преобразовать в двоичный файл

Стефан Шазелас
источник
1

Для двоичного и шестнадцатеричного использования: инструмент xxd в linux, а для двоичного в десятичное - инструмент qalculate.

Для получения справки о типе xxd xxd --helpили man xxdв Linux.

P4cK3tHuNt3R
источник
1

Вы можете использовать PHP:

$ php -r 'printf("%b", 11);'
1011

Или Perl:

$ perl -e 'print unpack("B*", pack("c", 11))'
00001011

$ perl -e 'print unpack("B*", pack("C", 11))'
00001011

$ perl -e 'print unpack("B*", pack("W", 11))'
00001011

$ perl -e 'print unpack("B*", pack("n", 11))'
0000000000001011

$ perl -e 'print unpack("B*", pack("N", 11))'
00000000000000000000000000001011

Или POSIX Awk svnpenn / stdlib :

$ awklib 'BEGIN {print mt_basecon(1011, 2, 16)}'
B

$ awklib 'BEGIN {print mt_basecon(1011, 2, 10)}'
11

$ awklib 'BEGIN {print mt_basecon("B", 16, 2)}'
1011

$ awklib 'BEGIN {print mt_basecon(11, 10, 2)}'
1011
Стивен Пенни
источник
0

Как упомянуто в предыдущем ответе, вы можете сделать Binary to Decimal и Hexa Decimal следующим образом в Bash, используя echo и printf. Я просто добавляю сюда, как конвертировать из десятичного числа и шестнадцатеричного в двоичный, используя чистый Bash.

Двоичные в десятичные с использованием эхо

echo "$((2#101010101))"
341

Двоичные в гекса-десятичные с использованием printf

printf '%x\n' "$((2#101010101))"
155

Целочисленное десятичное в двоичное преобразование с использованием только Bash

Используя только Bash, если вы хотите преобразовать десятичное число в двоичное, вы можете сделать это следующим образом:

touch dec2bin && chmod +x "$_" && vim "$_"

А затем скопируйте и вставьте следующее:

#!/bin/bash
## converting decimal integer to binary, pass int as a parameter
num=$1;
dec2bin()
{   [ "$num" == "" ] && { printf "Error: Pass an integer\n"; exit 1; };
    op=2; ## Since we're converting to binary
    quo=$(( $num / $op)); rem=$(( $num % $op)); ## quotient and remainder
    remarray=(); ## array for putting remainder inside array
    remarray+=("$rem"); ## array expansion
        until [[ $quo -eq 0 ]]; do
            num=$quo; quo=$(( $num / $op)); ## looping to get all remainder untill 0
            rem=$(( $num % $op)); remarray+="$rem"; ## array expansion
        done
    binary=$(echo "${remarray[@]}" | rev); ## reversing array
    printf "$binary\n"; ## printing reversed array
}
main()
{   [[ -n ${num//[0-9]/} ]] &&
        { printf "Error: $num is not an integer bruv!\n"; return 1;
        } || { dec2bin $num; }
}
main;

А затем попробуйте оттуда, где вы сохранили:

./dec2bin 420
110100100

Необходимо добавить целое число !!

./dec2bin 420.py
420.py is not an integer bruv!

Шестнадцатеричное преобразование в двоичное с использованием только Bash

Аналогично, от шестнадцатеричного до двоичного, как показано ниже, используя только bash:

#!/usr/local/bin/bash
## converting hexadecimal to binary, pass hex as a parameter
hex=$1;
hex2bin()
{   [ "$hex" == "" ] && { printf "Error: Pass a hex\n"; exit 1; };
    op=2; num=$((16#$hex)); ## converting hex to integer
    quo=$(( $num/ $op)); rem=$(( $num% $op)); ## quotient and remainder
    remarray=(); remarray+=("$rem"); ## array expansion
        until [[ $quo -eq 0 ]]; do
            num=$quo; quo=$(( $num / $op)); ## looping to get all remainder untill 0
            rem=$(( $num % $op)); remarray+="$rem"; ## array expansion
        done
    binary=$(echo "${remarray[@]}" | rev); ## reversing array
    printf "$binary\n"; ## printing reversed array
}
main()
{
[[ -n ${hex//[0-9,A-F,a-f]/} ]] &&
    { printf "Error: $hex is not a hex bruv!\n"; return 1;
    } || { hex2bin $hex; }
}
main;

Например:

./hex2bin 1aF
110101111

Шестнадцатеричное должно быть передано:

./hex2bin.bash XyZ
XyZ is not a hexa decimal number bruv!
Ракиб Фиха
источник