Convertir decimal a hexadecimal en un script de shell de UNIX

110

En un script de shell de UNIX, ¿qué puedo usar para convertir números decimales en hexadecimales? Pensé que od haría el truco, pero no me doy cuenta de que lo estoy alimentando con representaciones ASCII de números.

printf? ¡Bruto! Usándolo por ahora, pero ¿qué más hay disponible?

skiphoppy
fuente
8
Tengo que preguntar, ¿qué tiene de asqueroso printf? Muchos lenguajes de programación comunes admiten el formato de printf, por lo que las soluciones de printf a continuación seguramente serían las más fáciles de entender para los desarrolladores.
Michael Scheper
4
Vaya, no lo sé, ¡eso fue hace cinco años! Creo que tal vez pensé que no era un verdadero caparazón o algo así.
skiphoppy

Respuestas:

108
echo "obase=16; 34" | bc

Si desea filtrar un archivo completo de enteros, uno por línea:

( echo "obase=16" ; cat file_of_integers ) | bc
Bill Karwin
fuente
1
Miré a bc (1) y dc (1) y me perdí esa.
Keltia
3
@skiphoppy: Si escribe: echo "obase = 16; 12 34 56" | bc obtiene 1E240, lo mismo que si escribiera: echo "obase = 16; 123456" | antes de Cristo. Entonces, la forma de lidiar con números arbitrarios de enteros en una línea es poner cada número en su propia línea: tr '' '\ 015' <input | bc (asignar espacios en blanco a nuevas líneas).
Jonathan Leffler
1
Esto es genial si tiene 'bc', pero 'printf' es parte de bash en sí mismo
fuzzyTew
1
@Bill Karwin, o zsh, o busybox, pero tal vez no algún shell que no haya probado. Ya no mantengo simple sh instalado, pero claramente skiphoppy está buscando qué otras opciones hay
fuzzyTew
2
@ Sridhar-Sarnobat, esto es decimal a hexadecimal. Supongo que te refieres a convertir hexadecimal en dec. Para hacer eso, configure ibase=16. Es posible que desee leer el manual sobre bc para obtener más detalles.
Bill Karwin
186

Intentado printf(1)?

printf "%x\n" 34
22

Probablemente hay formas de hacer eso con funciones integradas en todos los shells, pero sería menos portátil. No he comprobado las especificaciones de POSIX sh para ver si tiene tales capacidades.

Keltia
fuente
5
No tiene mucho más POSIX que printf. Esto incluso funciona en "sh".
Orwellophile
4
printf no es una precisión arbitraria. bces. por ejemplo, tomando 238862874857408875879219909679752457540como entrada, printf nos da "Resultado demasiado grande". el método BC funciona muy bien para cosas más grandes que un int / long / bigint estándar
Andrew Backer
3
Y, si quieres letras mayúsculas en hexadecimal, printf "%X"
úsalas
3
Y para forzar una salida como "0x00", puede usar printf "0x% 02X"
gbetous
1
... y bcno está disponible en todas partes (al menos no en mi Linux integrado).
Matthieu
69

Hexadecimal a decimal:

$ echo $((0xfee10000))
4276158464

Decimal a hexadecimal:

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

bash-4.2$ printf -v hex '%x' 4294967295
bash-4.2$ echo $hex
ffffffff
Orwellophile
fuente
1
-v VARes una extensión de bash. No mencionado en la página del manual , revelado solo si uno llama printfsin argumentos
Adrian W
5

Perdón por mi culpa, prueba esto ...

#!/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}"

Ejemplo:

$ ./dtoh 1024
400
pjhobbs
fuente
1
Gracias esto ayudó mucho para env. donde printfy los hexcomandos no están disponibles.
benchuk
2
@benchuk donde printfno está disponible?
Matthieu
4

Tratar:

printf "%X\n" ${MY_NUMBER}
Rob Wells
fuente
2

En mi caso, me encontré con un problema al usar la solución printf:

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

La forma más fácil fue usar la solución con bc , sugerida en la publicación anterior:

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

Daniel Jeznach
fuente
¿Qué agrega su solución a las escritas años antes?
Matthieu
1
@Matthieu Menciona el problema de los números con ceros a la izquierda, que Bash printf interpreta inútilmente como octal, y demuestra una solución que evita el 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
fuente
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
fuente
1

Este no es un script de shell, pero es la herramienta cli que estoy usando para convertir 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
fuente