Converter decimal em hexadecimal no script de shell do UNIX

110

Em um script de shell do UNIX, o que posso usar para converter números decimais em hexadecimais? Achei que o od faria o truque, mas não estou percebendo que estou alimentando com representações ASCII de números.

printf? Bruto! Usando por agora, mas o que mais está disponível?

skiphoppy
fonte
8
Tenho que perguntar o que há de nojento em printf? Muitas linguagens de programação comuns suportam formatação semelhante a printf, então as soluções printf abaixo certamente seriam as mais fáceis para os desenvolvedores entenderem.
Michael Scheper
4
Rapaz, não sei - isso foi há cinco anos! Acho que pensei que não era uma casca de verdade ou algo assim.
skiphoppy

Respostas:

108
echo "obase=16; 34" | bc

Se você deseja filtrar um arquivo inteiro de inteiros, um por linha:

( echo "obase=16" ; cat file_of_integers ) | bc
Bill Karwin
fonte
1
Eu olhei para bc (1) e dc (1) e perdi aquele.
Keltia
3
@skiphoppy: Se você escrever: echo "obase = 16; 12 34 56" | bc você obtém 1E240, exatamente o mesmo como se você escrevesse: echo "obase = 16; 123456" | bc. Portanto, a maneira de lidar com números arbitrários de inteiros em uma linha é colocar cada número em sua própria linha: tr '' '\ 015' <input | bc (mapeia os espaços em branco para novas linhas).
Jonathan Leffler
1
Isso é ótimo se você tiver 'bc', mas 'printf' faz parte do próprio bash
fuzzyTew
1
@Bill Karwin, ou zsh ou busybox, mas talvez não algum shell que eu não tentei? Eu não mantenho o sh puro instalado mais, mas claramente skiphoppy está procurando por outras opções que existem
fuzzyTew
2
@ Sridhar-Sarnobat, é decimal para hexadecimal. Suponho que você queira dizer converter hex para dez. Para fazer isso, defina ibase=16. Você pode querer ler o manual em bc para mais detalhes.
Bill Karwin
186

Tentou printf(1)?

printf "%x\n" 34
22

Provavelmente, existem maneiras de fazer isso com funções integradas em todos os shells, mas seria menos portátil. Eu não verifiquei as especificações sh do POSIX para ver se ele tem tais recursos.

Keltia
fonte
5
Não fica muito mais POSIX do que printf. Isso funciona até em "sh".
Orwellophile de
4
printf não é precisão arbitrária. bcé. por exemplo, tomando 238862874857408875879219909679752457540como entrada, printf nos dá "Resultado muito grande". o método BC funciona muito bem para coisas maiores do que int / long / bigint padrão
Andrew Backer
3
E, se você quiser letras maiúsculas em hexadecimal, use printf "%X"com X maiúsculo.
andrybak
3
E para forçar uma saída como "0x00", você pode usar printf "0x% 02X"
gbetous
1
... e bcnão está disponível em todos os lugares (pelo menos não no meu Linux embarcado).
Matthieu
69

Hexidecimal para decimal:

$ echo $((0xfee10000))
4276158464

Decimal para hexadecimal:

$ printf '%x\n' 26
1a
pjhobbs
fonte
15
bash-4.2$ printf '%x\n' 4294967295
ffffffff

bash-4.2$ printf -v hex '%x' 4294967295
bash-4.2$ echo $hex
ffffffff
Orwellophile
fonte
1
-v VARé uma extensão do bash. Não mencionado na página do manual , revelado apenas se alguém chamar printfsem argumentos
Adrian W
5

Desculpe minha culpa, tente isso ...

#!/bin/bash
:

declare -r HEX_DIGITS="0123456789ABCDEF"

dec_value=$1
hex_value=""

until [ $dec_value == 0 ]; do

    rem_value=$((dec_value % 16))
    dec_value=$((dec_value / 16))

    hex_digit=${HEX_DIGITS:$rem_value:1}

    hex_value="${hex_digit}${hex_value}"

done

echo -e "${hex_value}"

Exemplo:

$ ./dtoh 1024
400
pjhobbs
fonte
1
Obrigado, isso ajudou muito para env. onde printfe os hexcomandos não estão disponíveis.
benchuk
2
@benchuk onde printfnão está disponível?
Matthieu de
4

Experimentar:

printf "%X\n" ${MY_NUMBER}
Rob Wells
fonte
3

Em zshvocê pode fazer este tipo de coisa:

% typeset -i 16 y
% print $(( [#8] x = 32, y = 32 ))
8#40
% print $x $y
8#40 16#20
% setopt c_bases
% print $y
0x20

Exemplo retirado da zshpágina de documentos sobre avaliação aritmética .

Eu acredito que o Bash tem recursos semelhantes.

Alastair
fonte
2

No meu caso, me deparei com um problema com o uso da solução printf:

$ printf "%x" 008 bash: printf: 008: invalid octal number

A maneira mais fácil era usar a solução com bc , sugerida no post superior:

$ bc <<< "obase=16; 008" 8

Daniel Jeznach
fonte
O que a sua solução adiciona às que foram escritas anos antes?
Matthieu de
1
@Matthieu Menciona a questão dos números com zeros à esquerda, que Bash printf interpreta inutilmente como octal, e demonstra uma solução que evita o problema.
mwfearnley
2
xd() {
    printf "hex> "
    while read i
    do
        printf "dec  $(( 0x${i} ))\n\nhex> "
    done
}
dx() {
    printf "dec> "
    while read i
    do
        printf 'hex  %x\n\ndec> ' $i
    done
}
sjas
fonte
1
# number conversion.

while `test $ans='y'`
do
    echo "Menu"
    echo "1.Decimal to Hexadecimal"
    echo "2.Decimal to Octal"
    echo "3.Hexadecimal to Binary"
    echo "4.Octal to Binary"
    echo "5.Hexadecimal to  Octal"
    echo "6.Octal to Hexadecimal"
    echo "7.Exit"

    read choice
    case $choice in

        1) echo "Enter the decimal no."
           read n
           hex=`echo "ibase=10;obase=16;$n"|bc`
           echo "The hexadecimal no. is $hex"
           ;;

        2) echo "Enter the decimal no."
           read n
           oct=`echo "ibase=10;obase=8;$n"|bc`
           echo "The octal no. is $oct"
           ;;

        3) echo "Enter the hexadecimal no."
           read n
           binary=`echo "ibase=16;obase=2;$n"|bc`
           echo "The binary no. is $binary"
           ;;

        4) echo "Enter the octal no."
           read n
           binary=`echo "ibase=8;obase=2;$n"|bc`
           echo "The binary no. is $binary"
           ;;

        5) echo "Enter the hexadecimal no."
           read n
           oct=`echo "ibase=16;obase=8;$n"|bc`
           echo "The octal no. is $oct"
           ;;

        6) echo "Enter the octal no."
           read n
           hex=`echo "ibase=8;obase=16;$n"|bc`
           echo "The hexadecimal no. is $hex"
           ;;

        7) exit 
        ;;
        *) echo "invalid no." 
        ;;

    esac
done
amol s. patil
fonte
1

Este não é um script de shell, mas é a ferramenta cli que estou usando para converter números entre bin / oct / dec / hex:

    #!/usr/bin/perl

    if (@ARGV < 2) {
      printf("Convert numbers among bin/oct/dec/hex\n");
      printf("\nUsage: base b/o/d/x num num2 ... \n");
      exit;
    }

    for ($i=1; $i<@ARGV; $i++) {
      if ($ARGV[0] eq "b") {
                    $num = oct("0b$ARGV[$i]");
      } elsif ($ARGV[0] eq "o") {
                    $num = oct($ARGV[$i]);
      } elsif ($ARGV[0] eq "d") {
                    $num = $ARGV[$i];
      } elsif ($ARGV[0] eq "h") {
                    $num = hex($ARGV[$i]);
      } else {
                    printf("Usage: base b/o/d/x num num2 ... \n");
                    exit;
      }
      printf("0x%x = 0d%d = 0%o = 0b%b\n", $num, $num, $num, $num);
    }
CodyChan
fonte