Binário para hexadecimal e decimal em um script de shell

20

Eu tenho um contexto onde eu preciso converter binário em hexadecimal e decimal e vice-versa em um script de shell. Alguém pode me sugerir uma ferramenta para isso?

Bangi
fonte
7
Vendo as respostas recentes, talvez você deva especificar se "binário" significa número binário ou arquivo binário .
manatwork
11
possível duplicado entre sites de: stackoverflow.com/questions/13280131/… e stackoverflow.com/questions/378829/…
Ciro Santilli Enviado em

Respostas:

39

É bastante simples fazer a conversão do binário no bash puro ( echoe printfsão embutidos):

Binário para decimal

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

Binário para hexadecimal

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

Voltando ao binário usando o bash sozinho é um pouco mais complexo, então sugiro que você veja as outras respostas para soluções para isso.

Chris Down
fonte
que tal decimal para hexadecimal.
Bangi
2
@ Bangi Basta fazer printf '%x\n' 10, por exemplo.
19413 Chris Down
11
Qual é o sentido de usar printf %dpara o bin2dec? $(( ... ))já dá um resultado decimal, echoé suficiente.
Andrea Corbellini
@AndreaCorbellini - Preferência pessoal. Em geral, eu uso em printf '%s\n' foovez de echopor vários motivos (principalmente portabilidade), pelo mesmo motivo, não o uso aqui.
21713 Chris Down
@ ChrisDown: Eu pensei que essa pergunta fosse explicitamente sobre o Bash (que tem um buildin bem implementado echo). Minha culpa!
Andrea Corbellini
16

Supondo que por binário, você quer dizer dados binários como em dados com qualquer valor possível de bytes, incluindo 0 e não números de base 2:

Para converter de binário, od(standard), xxd(vem com vim) ou perl's unpackvêm à mente.

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*",$_)'

Agora, para converter novamente em binário, awk(padrão) xxd -rou perl's pack:

A partir da saída decimal de od -tu1ou perlacima:

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

A partir do hexa perlou xxd -pacima:

xxd -r -p
perl -pe 'chomp;$_=pack("H*",$_)'
Stéphane Chazelas
fonte
13

Você pode usar o bc para isso manipulando os parâmetros ibasee obase:

O truque é que você precisa ser explícito sobre as bases. Portanto, se seu ibase é 2, se você definir seu obase para 10, ele não fará nada, pois 10 no binário é 2. Portanto, você precisa usar a notação hexadecimal.

Então, binário para decimal seria (observe que obase é A)

Binário para decimal:

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

Binário para hexadecimal:

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

Se a 'base de saída' obasefor alterada primeiro, será mais fácil:

$> echo 'obase=10;ibase=2;11110001011010'|bc
15450
$> echo 'obase=16;ibase=2;11110001011010'|bc
3C5A
psarossy
fonte
6
Este segundo exemplo está errado - 'F' seria a base 15, não 16 (16 decimal em hexadecimal é 10, não F). Tente echo 'ibase=2;obase=F;1111qual deve ser igual a decimal 15, ou seja. F em hex. Ele sai como 10, que está na base 15 (dígitos 0-E). É também mais fácil se você indicar o obase primeiro , por exemplo: echo 'obase=16;ibase=2;1111'|bc. Sem confusão.
GOLDILOCKS
2
Agora é pior. Depois de definir ibase, você deve fornecer informações nessa base, mesmo para obase. Então, no seu exemplo seria echo 'ibase=2;obase=10000;11110001011010'|bc. Melhor ouvir os conselhos de goldilocks e reverter a ordem - primeiro set obase, então ibase.
26413 manatwork
3

Se você quer dizer converter números da base 2 para 10 ou 16 e vice-versa, bcé a ferramenta padrão para fazer isso, como já mencionado por psarossy .

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

Alguns shells, como o zshsuporte interno para conversão de base, fazem parte de seus operadores de expansão aritmética:

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

e assim por diante.

Ambos ksh93e zshtambém suportam:

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

Mas observe que, quando expandido, $binaryterá um prefixo 2#ou 16#(com o qual você pode remover) ${binary#*#}.

ksh93 também suporta:

printf "%..2d\n" 123

converter para binário.

Stéphane Chazelas
fonte
1

Para uso binário em hexadecimal: ferramenta xxd no linux e para binário em decimal, você pode usar a ferramenta qalculate.

Para obter ajuda sobre o tipo xxd xxd --helpou man xxdno Linux.

P4cK3tHuNt3R
fonte
1

Você pode usar o PHP:

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

Ou 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

Ou 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
Steven Penny
fonte
0

Conforme mencionado na resposta anterior, você pode executar Binário em Decimal e Hexa Decimal da seguinte maneira no Bash usando echo e printf. Estou apenas adicionando aqui como converter de decimal e hexadecimal para binário usando o Bash puro.

Binário para decimal usando eco

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

Binário para Hexa-Decimal usando printf

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

Conversão de decimal inteiro para binário usando apenas Bash

Usando apenas o Bash, se você quiser converter decimal em binário, faça o seguinte:

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

E copie e cole o seguinte:

#!/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;

E tente de onde você salvou:

./dec2bin 420
110100100

Inteiro deve ser adicionado !!

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

Conversão hexadecimal em binário usando apenas Bash

Da mesma forma, hexadecimal para binário, da seguinte maneira, usando apenas o 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;

Por exemplo:

./hex2bin 1aF
110101111

Hex deve ser passado:

./hex2bin.bash XyZ
XyZ is not a hexa decimal number bruv!
Rakib Fiha
fonte