Ubah desimal menjadi heksadesimal dalam skrip shell UNIX


110

Dalam skrip shell UNIX, apa yang dapat saya gunakan untuk mengubah bilangan desimal menjadi heksadesimal? Saya pikir od akan melakukan trik, tetapi tidak menyadari bahwa saya memberinya representasi angka ASCII.

printf? Kotor! Menggunakannya untuk saat ini, tetapi apa lagi yang tersedia?


8
Saya harus bertanya, apa yang menjijikkan tentang printf? Banyak bahasa pemrograman umum mendukung pemformatan seperti printf, jadi solusi printf di bawah ini pasti akan menjadi yang paling mudah dipahami oleh pengembang.
Michael Scheper

4
Wah, saya tidak tahu - itu lima tahun yang lalu! Saya pikir mungkin saya pikir itu bukan cangkang asli atau semacamnya.
skiphoppy

Jawaban:


108
echo "obase=16; 34" | bc

Jika Anda ingin memfilter seluruh file bilangan bulat, satu per baris:

( echo "obase=16" ; cat file_of_integers ) | bc

1
Saya melihat bc (1) dan dc (1) dan melewatkan yang satu itu.
Keltia

3
@skiphoppy: Jika Anda menulis: echo "obase = 16; 12 34 56" | bc Anda mendapatkan 1E240, sama seperti jika Anda menulis: echo "obase = 16; 123456" | bc. Jadi cara untuk menangani sembarang bilangan bulat dalam satu baris adalah dengan meletakkan setiap nomor pada barisnya sendiri: tr '' '\ 015' <input | bc (peta kosong ke baris baru).
Jonathan Leffler

1
Ini bagus jika Anda kebetulan memiliki 'bc', tetapi 'printf' adalah bagian dari bash itu sendiri
fuzzyTew

1
@Bill Karwin, atau zsh, atau busybox, tapi mungkin bukan shell yang belum saya coba? Saya tidak lagi memasang sh biasa tetapi jelas skiphoppy sedang mencari opsi lain yang ada
fuzzyTew

2
@ Sridhar-Sarnobat, ini adalah desimal ke heksadesimal. Saya berasumsi maksud Anda mengubah hex ke des. Untuk melakukan itu, setel ibase=16. Anda mungkin ingin membaca manual tentang bc untuk lebih jelasnya.
Bill Karwin

186

Sudah mencoba printf(1)?

printf "%x\n" 34
22

Mungkin ada cara untuk melakukan itu dengan fungsi bawaan di semua shell tetapi itu kurang portabel. Saya belum memeriksa spesifikasi POSIX sh untuk melihat apakah ia memiliki kemampuan seperti itu.


5
Ini tidak mendapatkan lebih banyak POSIX daripada printf. Ini bahkan bekerja di "sh".
Orwellophile

4
printf bukanlah presisi yang mutlak. bcadalah. misalnya, mengambil 238862874857408875879219909679752457540sebagai masukan, printf memberi kita "Hasil terlalu besar". metode BC bekerja sangat baik untuk hal-hal yang lebih besar dari int / long / bigint standar
Andrew Backer

3
Dan, jika Anda ingin huruf besar dalam hex, gunakan printf "%X"dengan huruf besar X.
andrybak

3
Dan untuk memaksakan keluaran seperti "0x00", Anda dapat menggunakan printf "0x% 02X"
gbetous

1
... dan bctidak tersedia di semua tempat (setidaknya tidak di Linux tertanam saya).
Matthieu

69

Heksadesimal ke desimal:

$ echo $((0xfee10000))
4276158464

Desimal ke heksadesimal:

$ 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 VARadalah ekstensi bash. Tidak disebutkan di halaman manual , terungkap hanya jika seseorang menelepon printftanpa argumen
Adrian W

5

Maaf salah saya, coba ini ...

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

Contoh:

$ ./dtoh 1024
400

1
Terima kasih, ini banyak membantu untuk env. dimana printfdan hexperintah tidak tersedia.
benchuk

2
@benchuk mana printftidak tersedia?
Matthieu



2

Dalam kasus saya, saya menemukan satu masalah dengan menggunakan solusi printf:

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

Cara termudah adalah menggunakan solusi dengan bc , disarankan di posting lebih tinggi:

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


Apa yang ditambahkan solusi Anda dengan yang telah ditulis beberapa tahun sebelumnya?
Matthieu

1
@Matthieu Ini menyebutkan masalah angka dengan nol di depan, yang Bash printf dengan tidak membantu menafsirkan sebagai oktal, dan menunjukkan solusi yang menghindari masalah.
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

Ini bukan skrip shell, tetapi ini adalah alat cli yang saya gunakan untuk mengonversi angka di antara bin / oktober / des / 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);
    }
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.