Heksadesimal Hingga Desimal di Shell Script

126

Adakah yang bisa membantu saya mengonversi angka heksadesimal menjadi angka desimal di skrip shell?

Misalnya, saya ingin mengonversi angka heksadesimal bfca3000menjadi desimal menggunakan skrip shell. Saya pada dasarnya menginginkan perbedaan dua angka heksadesimal.

Kode saya adalah:

var3=`echo "ibase=16; $var1" | bc`
var4=`echo "ibase=16; $var2" | bc`
var5=$(($var4-$var3))               # [Line 48]

Saat menjalankan, saya mendapatkan kesalahan ini:

Line 48: -: syntax error: operand expected (error token is "-")
VenkateshJN
sumber
Cara sebaliknya: stackoverflow.com/questions/378829/… . Pada dasarnya alat yang sama. Dan kemungkinan duplikat lintas situs: superuser.com/questions/226163/…
Ciro Santilli 郝海东 冠状 病 六四 事件 事件

Jawaban:

314

Untuk mengkonversi dari hex ke desimal, ada banyak cara untuk melakukannya di shell atau dengan program eksternal:

Dengan :

$ echo $((16#FF))
255

dengan :

$ echo "ibase=16; FF" | bc
255

dengan :

$ perl -le 'print hex("FF");'
255

dengan :

$ printf "%d\n" 0xFF
255

dengan :

$ python -c 'print(int("FF", 16))'
255

dengan :

$ ruby -e 'p "FF".to_i(16)'
255

dengan :

$ nodejs <<< "console.log(parseInt('FF', 16))"
255

dengan :

$ rhino<<EOF
print(parseInt('FF', 16))
EOF
...
255

dengan :

$ groovy -e 'println Integer.parseInt("FF",16)'
255
Gilles Quenot
sumber
1
Apa ? bc adalah Bahasa kalkulator presisi arbitrer : perintah eksternal.
Gilles Quenot
10
Sehingga ? inilah tujuan dari 4 perintah saya sebelum Anda mengubah arti pertanyaan Anda.
Gilles Quenot
2
Apakah printfsolusinya POSIX? Jika ya, itu yang terbaik :)
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功
3
Dalam bash, Anda juga dapat menggunakan $((0xff)), misalnya dengan awalan hex mirip-C alih-alih 16#, meskipun N#jelas lebih umum.
Ruslan
3
Contoh bash pertama rentan terhadap kesalahan integer overflow, misalnya echo $((077E9F2DBF49D100001#FF))meluap batas integer 64-bit 2 ^ 64. bcmenangani ini dengan benar.
roblogic
39

Berurusan dengan versi embeddedbox busybox yang sangat ringan di Linux berarti banyak perintah tradisional tidak tersedia (bc, printf, dc, perl, python)

echo $((0x2f))
47

hexNum=2f
echo $((0x${hexNum}))
47

Penghargaan untuk Peter Leung untuk solusi ini.

hinekyle
sumber
1
OK tapi hati-hati terhadap kesalahan integer overflow, misalnya echo $((0x077E9F2DBF49D100001))meluap batas integer 64-biit sebesar 2 ^ 64. bcmenangani ini dengan benar
roblog
13

Satu lagi cara untuk melakukannya menggunakan shell (bash atau ksh, tidak bekerja dengan tanda hubung):

echo $((16#FF))
255
Tomás Fox
sumber
Apa arti #simbol itu? Apakah ada aplikasi atau dokumentasi lain untuk membaca lebih lanjut tentang penggunaannya?
user1527227
1
Disebutkan di sini: tautan . Pada akhir bagian 6.5 dikatakan: "... angka mengambil bentuk [basis #] n, di mana basis opsional adalah angka desimal antara 2 dan 64 yang mewakili basis aritmatika, dan n adalah angka dalam basis itu. Jika basis # dihilangkan, maka basis 10 digunakan. Digit lebih besar dari 9 diwakili oleh huruf kecil, huruf besar, '@', dan '_', dalam urutan itu. Jika basis kurang dari atau sama dengan 36, huruf kecil dan huruf besar dapat digunakan secara bergantian untuk mewakili angka antara 10 dan 35. "
Tomás Fox
11

Berbagai alat tersedia untuk Anda dari dalam shell. Sputnick telah memberi Anda tinjauan yang sangat baik dari opsi Anda, berdasarkan pertanyaan awal Anda. Dia pasti pantas memilih karena dia menghabiskan banyak waktu memberikan jawaban yang benar.

Satu lagi yang tidak ada dalam daftar:

[ghoti@pc ~]$ dc -e '16i BFCA3000 p'
3217698816

Tetapi jika semua yang ingin Anda lakukan adalah mengurangi, mengapa repot-repot mengubah input ke basis 10?

[ghoti@pc ~]$ dc -e '16i BFCA3000 17FF - p 10o p'
3217692673
BFCA1801
[ghoti@pc ~]$ 

The dcperintah "meja calc". Ini juga akan mengambil input dari stdin, seperti bc, tetapi alih-alih menggunakan "urutan operasi", ia menggunakan notasi susun ("reverse Polish"). Anda memberikan input yang ditambahkan ke tumpukan, lalu memberikannya operator yang mengeluarkan item dari tumpukan, dan menekan kembali hasilnya.

Pada perintah di atas kita punya yang berikut ini:

  • 16i- Memberitahu dc untuk menerima input pada basis 16 (heksadesimal). Tidak mengubah basis output.
  • BFCA3000 - nomor awal Anda
  • 17FF - nomor hex acak yang saya pilih untuk mengurangi angka awal Anda
  • - - ambil dua angka yang kami dorong, dan kurangi yang kemudian dari yang sebelumnya, lalu dorong hasilnya kembali ke tumpukan
  • p- cetak item terakhir pada tumpukan. Ini tidak mengubah tumpukan, jadi ...
  • 10o - memberitahu dc untuk mencetak outputnya di basis "10", tetapi ingat bahwa skema penomoran input kami saat ini heksadesimal, jadi "10" berarti "16".
  • p - cetak item terakhir pada tumpukan lagi ... kali ini dalam hex.

Anda dapat membangun solusi matematika yang sangat rumit dengan dc. Ini hal yang baik untuk ada di kotak peralatan Anda untuk skrip shell.

ghoti
sumber
3

Kesalahan seperti yang dilaporkan muncul ketika variabelnya nol (atau kosong):

$ unset var3 var4; var5=$(($var4-$var3))
bash: -: syntax error: operand expected (error token is "-")

Itu bisa terjadi karena nilai yang diberikan kepada bc salah. Mungkin saja bc membutuhkan nilai-nilai UPPERcase. Itu perlu BFCA3000, bukan bfca3000. Itu mudah diperbaiki di bash, cukup gunakan ^^ekspansi:

var3=bfca3000; var3=`echo "ibase=16; ${var1^^}" | bc`

Itu akan mengubah skrip menjadi ini:

#!/bin/bash

var1="bfca3000"
var2="efca3250"

var3="$(echo "ibase=16; ${var1^^}" | bc)"
var4="$(echo "ibase=16; ${var2^^}" | bc)"

var5="$(($var4-$var3))"

echo "Diference $var5"

Tetapi tidak perlu menggunakan bc [1], karena bash dapat melakukan terjemahan dan substraksi secara langsung:

#!/bin/bash

var1="bfca3000"
var2="efca3250"

var5="$(( 16#$var2 - 16#$var1 ))"

echo "Diference $var5"

[1] Catatan: Saya mengasumsikan nilainya dapat direpresentasikan dalam matematika 64 bit, karena perbedaannya dihitung dalam bash dalam skrip asli Anda. Bash terbatas pada bilangan bulat kurang dari ((2 ** 63) -1) jika dikompilasi dalam 64 bit. Itu akan menjadi satu-satunya perbedaan dengan bc yang tidak memiliki batas seperti itu.


sumber
3

Di dash dan shell lainnya, Anda bisa menggunakan

printf "%d\n" (your hexadecimal number)

untuk mengubah angka heksadesimal menjadi desimal. Ini bukan bash, atau ksh, spesifik.

pemula
sumber
1
misprintf "%d" 0xff
lashgar