เลขฐานสิบหกถึงทศนิยมในเชลล์สคริปต์


126

มีใครช่วยฉันแปลงเลขฐานสิบหกเป็นเลขฐานสิบในเชลล์สคริปต์ได้ไหม

เช่นฉันต้องการแปลงเลขฐานสิบหกเป็นฐานสิบbfca3000โดยใช้เชลล์สคริปต์ โดยพื้นฐานแล้วฉันต้องการความแตกต่างของเลขฐานสิบหกสองตัว

รหัสของฉันคือ:

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

เมื่อดำเนินการฉันได้รับข้อผิดพลาดนี้:

Line 48: -: syntax error: operand expected (error token is "-")

อีกทางหนึ่ง: stackoverflow.com/questions/378829/… . โดยพื้นฐานแล้วเครื่องมือเดียวกัน และเป็นไปได้ข้ามไซต์ที่ซ้ำกัน: superuser.com/questions/226163/…
Ciro Santilli 郝海东冠状病六四事件法轮功

คำตอบ:


315

ในการแปลงจากฐานสิบหกเป็นฐานสิบมีหลายวิธีในการทำในเชลล์หรือด้วยโปรแกรมภายนอก:

กับ :

$ echo $((16#FF))
255

กับ :

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

กับ :

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

กับ :

$ printf "%d\n" 0xFF
255

กับ :

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

กับ :

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

กับ :

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

กับ :

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

กับ :

$ groovy -e 'println Integer.parseInt("FF",16)'
255

1
อะไร ? bc เป็นภาษาเครื่องคำนวณความแม่นยำโดยพลการ : คำสั่งภายนอก
Gilles Quenot

11
และ SO? นี่คือจุดประสงค์ของ 4 คำสั่งของฉันก่อนที่คุณจะปรับเปลี่ยนความรู้สึกของคำถามของคุณ
Gilles Quenot

3
เป็นprintfวิธีการแก้ปัญหา POSIX? ถ้าใช่ก็ดีที่สุด :)
Ciro Santilli 郝海东郝海东冠状病六四法轮功

3
ใน bash คุณยังสามารถใช้$((0xff))เช่นกับ C-like hex prefix แทน16#แม้ว่าN#จะชัดเจนกว่าทั่วไป
Ruslan

3
ตัวอย่าง bash แรกมีความอ่อนไหวต่อข้อผิดพลาดจำนวนเต็มล้นเช่นecho $((077E9F2DBF49D100001#FF))ล้นขีด จำกัด จำนวนเต็ม 64 บิตที่ 2 ^ 64 bcจัดการสิ่งนี้อย่างเหมาะสม
roblogic

39

การจัดการกับ busybox เวอร์ชันฝังตัวที่มีน้ำหนักเบามากบน Linux หมายความว่าคำสั่งดั้งเดิมจำนวนมากไม่สามารถใช้งานได้ (bc, printf, dc, perl, python)

echo $((0x2f))
47

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

ให้เครดิตกับPeter Leungสำหรับการแก้ปัญหานี้


1
ตกลง แต่ระวังข้อผิดพลาดจำนวนเต็มล้นเช่นecho $((0x077E9F2DBF49D100001))เกินขีด จำกัด จำนวนเต็ม 64 ไบต์ที่ 2 ^ 64 bcจัดการสิ่งนี้อย่างถูกต้อง
roblogic

13

อีกวิธีหนึ่งในการใช้เชลล์ (bash หรือ ksh ใช้ไม่ได้กับเส้นประ):

echo $((16#FF))
255

อะไร#เป็นสัญลักษณ์หมายถึงอะไร? มีแอปพลิเคชันหรือเอกสารประกอบอื่น ๆ เพื่ออ่านเพิ่มเติมเกี่ยวกับการใช้งานหรือไม่?
user1527227

1
มันถูกกล่าวถึงที่นี่: การเชื่อมโยง ในตอนท้ายของส่วน 6.5 มีข้อความว่า: "... ตัวเลขอยู่ในรูป [ฐาน #] n โดยที่ฐานเสริมคือเลขฐานสิบระหว่าง 2 ถึง 64 แทนฐานเลขคณิตและ n คือตัวเลขในฐานนั้นถ้า ฐาน # ถูกละไว้จากนั้นจะใช้ฐาน 10 ตัวเลขที่มากกว่า 9 จะแสดงด้วยอักษรตัวพิมพ์เล็กตัวพิมพ์ใหญ่ "@" และ "_" ตามลำดับนั้นหากฐานน้อยกว่าหรือเท่ากับ 36 ตัวพิมพ์เล็กและตัวพิมพ์ใหญ่อาจใช้แทนกันได้เพื่อแสดงตัวเลขระหว่าง 10 ถึง 35 "
Tomás Fox

11

คุณมีเครื่องมือมากมายจากภายในเชลล์ Sputnick ให้ภาพรวมที่ยอดเยี่ยมเกี่ยวกับตัวเลือกของคุณตามคำถามเริ่มต้นของคุณ เขาสมควรได้รับคะแนนโหวตตลอดเวลาที่เขาให้คำตอบที่ถูกต้องแก่คุณหลายคำตอบ

อีกหนึ่งรายการที่ไม่ได้อยู่ในรายชื่อของเขา:

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

แต่ถ้าสิ่งที่คุณต้องการทำคือลบทำไมต้องเปลี่ยนอินพุตเป็นฐาน 10

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

dcคำสั่งคือ "โต๊ะ Calc" นอกจากนี้ยังใช้อินพุตจาก stdin เช่นbcแต่แทนที่จะใช้ "ลำดับการดำเนินการ" จะใช้สัญกรณ์แบบซ้อน ("reverse Polish") คุณให้อินพุตที่มันเพิ่มลงในสแต็กจากนั้นให้โอเปอเรเตอร์ที่ป๊อปไอเท็มออกจากสแต็กและดันผลลัพธ์กลับไป

ในคำสั่งด้านบนเรามีสิ่งต่อไปนี้:

  • 16i- บอกให้ dc ยอมรับอินพุตในฐาน 16 (เลขฐานสิบหก) ไม่เปลี่ยนฐานเอาต์พุต
  • BFCA3000 - หมายเลขเริ่มต้นของคุณ
  • 17FF - เลขฐานสิบหกแบบสุ่มที่ฉันเลือกเพื่อลบออกจากหมายเลขเริ่มต้นของคุณ
  • - - นำตัวเลขสองตัวที่เราผลักดันและลบตัวเลขที่ตามมาจากตัวเลขก่อนหน้านี้จากนั้นผลักผลลัพธ์กลับไปที่สแต็ก
  • p- พิมพ์รายการสุดท้ายบนสแต็ก นี่ไม่ได้เปลี่ยนสแต็คดังนั้น ...
  • 10o - บอกให้ dc พิมพ์เอาต์พุตในฐาน "10" แต่โปรดจำไว้ว่ารูปแบบการกำหนดหมายเลขอินพุตของเราในปัจจุบันเป็นเลขฐานสิบหกดังนั้น "10" จึงหมายถึง "16"
  • p - พิมพ์รายการสุดท้ายบนสแต็กอีกครั้ง ... คราวนี้เป็นเลขฐานสิบหก

คุณสามารถสร้างโซลูชันทางคณิตศาสตร์ที่ซับซ้อนได้ด้วย dc เป็นสิ่งที่ดีที่จะมีในกล่องเครื่องมือของคุณสำหรับเชลล์สคริปต์


3

ข้อผิดพลาดตามที่รายงานจะปรากฏขึ้นเมื่อตัวแปรเป็นโมฆะ (หรือว่างเปล่า):

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

ที่อาจเกิดขึ้นเนื่องจากค่าที่กำหนดให้กับ bc ไม่ถูกต้อง นั่นอาจเป็นไปได้ว่า bc ต้องการค่า UPPERcase มันต้องไม่BFCA3000 bfca3000ที่แก้ไขได้อย่างง่ายดายใน bash เพียงใช้ส่วน^^ขยาย:

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

ที่จะเปลี่ยนสคริปต์เป็นสิ่งนี้:

#!/bin/bash

var1="bfca3000"
var2="efca3250"

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

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

echo "Diference $var5"

แต่ไม่จำเป็นต้องใช้ bc [1] เนื่องจาก bash สามารถทำการแปลและการย่อยได้โดยตรง:

#!/bin/bash

var1="bfca3000"
var2="efca3250"

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

echo "Diference $var5"

[1] หมายเหตุ: ฉันสมมติว่าค่าสามารถแสดงในคณิตศาสตร์ 64 บิตได้เนื่องจากความแตกต่างคำนวณเป็น bash ในสคริปต์ต้นฉบับของคุณ Bash ถูก จำกัด ไว้ที่จำนวนเต็มน้อยกว่า ((2 ** 63) -1) หากคอมไพล์เป็น 64 บิต นั่นจะเป็นข้อแตกต่างเพียงอย่างเดียวกับ bc ซึ่งไม่มีขีด จำกัด ดังกล่าว


3

คุณสามารถใช้

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

เพื่อแปลงเลขฐานสิบหกเป็นฐานสิบ นี่ไม่ใช่ bash หรือ ksh เฉพาะ


1
เช่นprintf "%d" 0xff
lashgar
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.