ไบนารีฐานสิบหกและทศนิยมในเชลล์สคริปต์


20

ฉันมีบริบทที่ฉันต้องแปลงเลขฐานสองเป็นเลขฐานสิบหกและทศนิยมและ viceversa ในเชลล์สคริปต์ มีคนแนะนำฉันเป็นเครื่องมือสำหรับสิ่งนี้ได้ไหม


7
เห็นคำตอบที่ผ่านมาบางทีคุณอาจจะระบุว่า“ฐาน” หมายถึงเลขฐานสองหรือแฟ้มไบนารี
จัดการ

1
ไซต์ข้ามที่เป็นไปได้ซ้ำกันของ: stackoverflow.com/questions/13280131/…และstackoverflow.com/questions/378829/…
Ciro Santilli 新疆改造中心中心法轮功六四事件

คำตอบ:


39

มันค่อนข้างตรงไปตรงมาที่จะทำการแปลงจากไบนารี่ใน bash บริสุทธิ์ ( echoและprintfบิวด์อิน):

ไบนารีเป็นทศนิยม

$ echo "$((2#101010101))"
341

เลขฐานสองถึงเลขฐานสิบหก

$ printf '%x\n' "$((2#101010101))"
155

การกลับไปที่ไบนารีโดยใช้ bash เพียงอย่างเดียวนั้นค่อนข้างซับซ้อนกว่าดังนั้นฉันขอแนะนำให้คุณดูคำตอบอื่น ๆ สำหรับวิธีแก้ปัญหา


ทศนิยมเป็นเลขฐานสิบหก
Bangi

2
@ Bangi เพียงแค่ทำprintf '%x\n' 10เช่น
Chris Down

1
จุดประสงค์ของการใช้printf %dสำหรับ bin2dec คืออะไร? $(( ... ))ให้ผลลัพธ์ทศนิยมแล้วechoก็เพียงพอแล้ว
Andrea Corbellini

@AndreaCorbellini - การตั้งค่าส่วนตัว โดยทั่วไปฉันใช้printf '%s\n' fooแทนechoด้วยเหตุผลหลายประการ (ส่วนใหญ่พกพาได้) ด้วยเหตุผลเดียวกันฉันไม่ได้ใช้ที่นี่
Chris Down

@ChrisDown: ฉันคิดว่าคำถามนี้เกี่ยวกับ Bash (ซึ่งมีการติดตั้งมาอย่างดีecho) ความผิดฉันเอง!
Andrea Corbellini

16

สมมติว่าโดยไบนารี่คุณหมายถึงข้อมูลไบนารี่เช่นเดียวกับในข้อมูลที่มีค่าไบต์ที่เป็นไปได้รวมถึง 0 และไม่ใช่ตัวเลขฐาน 2:

การแปลงจากเลขฐานสองod(มาตรฐาน), xxd(มาพร้อมกับvim) หรือperl's unpackมาใจ

od -An -vtu1 # for decimal
od -An -vtx1 # for hexadecimal

xxd -p # for hexa

perl -pe 'BEGIN{$\="\n";$/=\30};$_=unpack("H*",$_)' # like xxd -p

# for decimal:
perl -ne 'BEGIN{$\="\n";$/=\30;$,=" "}; print unpack("C*",$_)'

ตอนนี้เมื่อต้องการแปลงกลับเป็นไบนารีawk(มาตรฐาน) xxd -rหรือperl's pack:

จากเอาต์พุตทศนิยมจากod -tu1หรือperlสูงกว่า:

LC_ALL=C awk '{for (i = 1; i <= NF; i++) printf "%c", $i}'
perl -ape '$_=pack("C*",@F)'

จาก hexa perlหรือxxd -pสูงกว่า:

xxd -r -p
perl -pe 'chomp;$_=pack("H*",$_)'

13

คุณสามารถใช้ bc สำหรับสิ่งนี้ได้โดยการจัดการibaseและobaseพารามิเตอร์:

เคล็ดลับคือคุณจะต้องมีความชัดเจนเกี่ยวกับฐาน ดังนั้นถ้า ibase ของคุณคือ 2 ดังนั้นถ้าคุณตั้ง obase ของคุณเป็น 10 มันจะไม่ทำอะไรเลยเพราะ 10 ในไบนารีคือ 2 ดังนั้นคุณต้องใช้สัญลักษณ์เลขฐานสิบหก

ดังนั้นไบนารีจะเป็นทศนิยม (ดูว่า obase คือ A)

ไบนารีถึงทศนิยม:

$> echo 'ibase=2;obase=A;11110001011010'|bc
15450

ไบนารีถึงฐานสิบหก:

$> echo 'ibase=2;obase=10000;11110001011010'|bc
3C5A

หาก 'ฐานเอาท์พุท' obaseมีการเปลี่ยนแปลงก่อนควรจะง่ายขึ้น:

$> echo 'obase=10;ibase=2;11110001011010'|bc
15450
$> echo 'obase=16;ibase=2;11110001011010'|bc
3C5A

6
ตัวอย่างที่สองนี้ผิด - 'F' จะเป็นฐาน 15 ไม่ใช่ 16 (ฐานสิบหกในฐานสิบหกคือ 10 ไม่ใช่ F) ลองใช้เลขทศนิยม 15 echo 'ibase=2;obase=F;1111ซึ่งควรจะเป็น F ในฐานสิบหก มันออกมาเป็น 10 ซึ่งอยู่ในฐาน 15 (หลัก 0-E) นอกจากนี้ยังง่ายถ้าคุณรัฐ obase แรกecho 'obase=16;ibase=2;1111'|bcเช่น: ไม่มีความสับสน
goldilocks

2
ตอนนี้มันแย่ที่สุด เมื่อคุณตั้งibaseคุณต้องให้ข้อมูลในที่obaseฐานแม้สำหรับ echo 'ibase=2;obase=10000;11110001011010'|bcดังนั้นในตัวอย่างของคุณจะ ดีกว่าฟังคำแนะนำ Goldilocks และกลับสั่งซื้อ - ชุดแรกแล้วobase ibase
จัดการ

3

ถ้าคุณหมายถึงการแปลงตัวเลขจากฐาน 2 ถึง 10 หรือ 16 และกลับมาbcเป็นเครื่องมือมาตรฐานที่จะทำตามที่กล่าวไว้แล้วโดยpsarossy

decimal=123
binary=$(echo "obase=2;$decimal" | bc)
hex=$(echo "obase=16;ibase=2;$binary" | bc)

เชลล์บางzshตัวมีการสนับสนุนในตัวสำหรับการแปลงฐานซึ่งเป็นส่วนหนึ่งของตัวดำเนินการส่วนขยายทางคณิตศาสตร์:

decimal=123
binary=$(([##2]decimal))
hex=$(([##16]decimal))
hex=$(([##16]2#$binary))
decimal=$((2#$binary))

และอื่น ๆ

ทั้งksh93และzshรองรับ:

typeset -i2 binary=123
typeset -i16 dec2hex=123 bin2hex='2#1111'

แต่ทราบว่าเมื่อขยาย$binaryจะมี2#หรือ16#คำนำหน้า ${binary#*#}(ซึ่งคุณสามารถตัดกับ

ksh93 ยังรองรับ:

printf "%..2d\n" 123

เพื่อแปลงเป็นไบนารี่


1

สำหรับการใช้เลขฐานสองถึงเลขฐานสิบหก: เครื่องมือxxdใน linux และสำหรับเลขฐานสองเป็นทศนิยมคุณสามารถใช้เครื่องมือ qalculate

สำหรับความช่วยเหลือเกี่ยวกับประเภท xxd xxd --helpหรือman xxdใน Linux


1

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

$ php -r 'printf("%b", 11);'
1011

หรือ Perl:

$ perl -e 'print unpack("B*", pack("c", 11))'
00001011

$ perl -e 'print unpack("B*", pack("C", 11))'
00001011

$ perl -e 'print unpack("B*", pack("W", 11))'
00001011

$ perl -e 'print unpack("B*", pack("n", 11))'
0000000000001011

$ perl -e 'print unpack("B*", pack("N", 11))'
00000000000000000000000000001011

หรือ POSIX Awk svnpenn / stdlib :

$ awklib 'BEGIN {print mt_basecon(1011, 2, 16)}'
B

$ awklib 'BEGIN {print mt_basecon(1011, 2, 10)}'
11

$ awklib 'BEGIN {print mt_basecon("B", 16, 2)}'
1011

$ awklib 'BEGIN {print mt_basecon(11, 10, 2)}'
1011

0

ดังที่ได้กล่าวไว้ในคำตอบก่อนหน้านี้คุณสามารถทำเลขฐานสองเป็นทศนิยมและฐานสิบหกดังต่อไปนี้ใน Bash โดยใช้ echo และ printf ฉันแค่เพิ่มที่นี่วิธีการแปลงจากทศนิยมและฐานสิบหกเป็นไบนารีโดยใช้ Bash บริสุทธิ์

ไบนารีถึงทศนิยมโดยใช้เสียงสะท้อน

echo "$((2#101010101))"
341

ไบนารีถึงฐานสิบหกโดยใช้ printf

printf '%x\n' "$((2#101010101))"
155

จำนวนเต็มทศนิยมเป็น Binary Conversion โดยใช้ Bash เท่านั้น

ใช้ Bash เท่านั้นหากคุณต้องการแปลงทศนิยมให้เป็นไบนารีคุณสามารถทำสิ่งต่อไปนี้:

touch dec2bin && chmod +x "$_" && vim "$_"

จากนั้นคัดลอกและวางต่อไปนี้:

#!/bin/bash
## converting decimal integer to binary, pass int as a parameter
num=$1;
dec2bin()
{   [ "$num" == "" ] && { printf "Error: Pass an integer\n"; exit 1; };
    op=2; ## Since we're converting to binary
    quo=$(( $num / $op)); rem=$(( $num % $op)); ## quotient and remainder
    remarray=(); ## array for putting remainder inside array
    remarray+=("$rem"); ## array expansion
        until [[ $quo -eq 0 ]]; do
            num=$quo; quo=$(( $num / $op)); ## looping to get all remainder untill 0
            rem=$(( $num % $op)); remarray+="$rem"; ## array expansion
        done
    binary=$(echo "${remarray[@]}" | rev); ## reversing array
    printf "$binary\n"; ## printing reversed array
}
main()
{   [[ -n ${num//[0-9]/} ]] &&
        { printf "Error: $num is not an integer bruv!\n"; return 1;
        } || { dec2bin $num; }
}
main;

จากนั้นลองจากที่คุณบันทึกไว้:

./dec2bin 420
110100100

ต้องเพิ่มจำนวนเต็ม !!

./dec2bin 420.py
420.py is not an integer bruv!

เลขฐานสิบหกเป็น Binary โดยใช้ Bash เท่านั้น

ในทำนองเดียวกันเลขฐานสิบหกถึงไบนารีดังต่อไปนี้ใช้ทุบตีเท่านั้น:

#!/usr/local/bin/bash
## converting hexadecimal to binary, pass hex as a parameter
hex=$1;
hex2bin()
{   [ "$hex" == "" ] && { printf "Error: Pass a hex\n"; exit 1; };
    op=2; num=$((16#$hex)); ## converting hex to integer
    quo=$(( $num/ $op)); rem=$(( $num% $op)); ## quotient and remainder
    remarray=(); remarray+=("$rem"); ## array expansion
        until [[ $quo -eq 0 ]]; do
            num=$quo; quo=$(( $num / $op)); ## looping to get all remainder untill 0
            rem=$(( $num % $op)); remarray+="$rem"; ## array expansion
        done
    binary=$(echo "${remarray[@]}" | rev); ## reversing array
    printf "$binary\n"; ## printing reversed array
}
main()
{
[[ -n ${hex//[0-9,A-F,a-f]/} ]] &&
    { printf "Error: $hex is not a hex bruv!\n"; return 1;
    } || { hex2bin $hex; }
}
main;

ตัวอย่างเช่น:

./hex2bin 1aF
110101111

Hex จะต้องผ่าน:

./hex2bin.bash XyZ
XyZ is not a hexa decimal number bruv!
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.