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?
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?
Respostas:
É bastante simples fazer a conversão do binário no bash puro ( echo
e printf
são embutidos):
$ echo "$((2#101010101))"
341
$ 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.
printf '%x\n' 10
, por exemplo.
printf %d
para o bin2dec? $(( ... ))
já dá um resultado decimal, echo
é suficiente.
printf '%s\n' foo
vez de echo
por vários motivos (principalmente portabilidade), pelo mesmo motivo, não o uso aqui.
echo
). Minha culpa!
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 unpack
vê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 -r
ou perl
's pack
:
A partir da saída decimal de od -tu1
ou perl
acima:
LC_ALL=C awk '{for (i = 1; i <= NF; i++) printf "%c", $i}'
perl -ape '$_=pack("C*",@F)'
A partir do hexa perl
ou xxd -p
acima:
xxd -r -p
perl -pe 'chomp;$_=pack("H*",$_)'
Você pode usar o bc para isso manipulando os parâmetros ibase
e 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' obase
for alterada primeiro, será mais fácil:
$> echo 'obase=10;ibase=2;11110001011010'|bc
15450
$> echo 'obase=16;ibase=2;11110001011010'|bc
3C5A
echo 'ibase=2;obase=F;1111
qual 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.
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
.
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 zsh
suporte 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 ksh93
e zsh
também suportam:
typeset -i2 binary=123
typeset -i16 dec2hex=123 bin2hex='2#1111'
Mas observe que, quando expandido, $binary
terá um prefixo 2#
ou 16#
(com o qual você pode remover) ${binary#*#}
.
ksh93
também suporta:
printf "%..2d\n" 123
converter para binário.
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 --help
ou man xxd
no Linux.
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
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!