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?


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

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.


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

15
bash-4.2$ printf '%x\n' 4294967295
ffffffff

bash-4.2$ printf -v hex '%x' 4294967295
bash-4.2$ echo $hex
ffffffff

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

1
Gracias esto ayudó mucho para env. donde printfy los hexcomandos no están disponibles.
benchuk

2
@benchuk donde printfno está disponible?
Matthieu



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


¿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
}

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

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);
    }
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.