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


110

ในเชลล์สคริปต์ UNIX ฉันจะใช้อะไรในการแปลงเลขฐานสิบเป็นเลขฐานสิบหกได้บ้าง ฉันคิดว่า od จะทำเคล็ดลับ แต่ก็ไม่รู้ว่าฉันกำลังป้อนตัวเลข ASCII

printf? ขั้นต้น! ใช้ตอนนี้ แต่มีอะไรอีกบ้าง?


8
ฉันต้องถามว่า printf มีอะไรบ้าง? ภาษาโปรแกรมทั่วไปจำนวนมากรองรับการจัดรูปแบบเหมือน printf ดังนั้นโซลูชัน printf ด้านล่างจึงเป็นวิธีที่ง่ายที่สุดสำหรับนักพัฒนาที่จะเข้าใจ
Michael Scheper

4
เด็กชายฉันไม่รู้ - เมื่อห้าปีก่อน! ฉันคิดว่าบางทีฉันอาจจะคิดว่ามันไม่ใช่เปลือกที่แท้จริงหรืออะไรสักอย่าง
skiphoppy

คำตอบ:


108
echo "obase=16; 34" | bc

หากคุณต้องการกรองไฟล์จำนวนเต็มหนึ่งไฟล์ต่อบรรทัด:

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

1
ฉันดูทั้ง bc (1) และ dc (1) แล้วคิดถึงอันนั้น
Keltia

3
@skiphoppy: ถ้าคุณเขียน: echo "obase = 16; 12 34 56" | bc คุณจะได้รับ 1E240 เหมือนกับที่คุณเขียนว่า: echo "obase = 16; 123456" | bc. ดังนั้นวิธีจัดการกับจำนวนเต็มตามอำเภอใจทั้งหมดในบรรทัดเดียวคือใส่ตัวเลขแต่ละตัวไว้ในบรรทัดของมันเอง: tr '' '\ 015' <input | bc (แมปช่องว่างเพื่อขึ้นบรรทัดใหม่)
Jonathan Leffler

1
นี่จะดีมากถ้าคุณมี 'bc' แต่ 'printf' เป็นส่วนหนึ่งของ bash เอง
fuzzyTew

1
@ Bill Karwin หรือ zsh หรือ busybox แต่อาจจะไม่ใช่เชลล์ที่ฉันไม่ได้ลอง? ฉันไม่ได้ติดตั้ง sh แบบธรรมดาอีกต่อไป แต่เห็นได้ชัดว่า skiphoppy กำลังมองหาตัวเลือกอื่น ๆ ที่มีอยู่
fuzzyTew

2
@ Sridhar-Sarnobat นี่คือทศนิยมเป็นเลขฐานสิบหก ฉันคิดว่าคุณหมายถึงแปลงฐานสิบหกเป็นธันวาคม ibase=16ต้องการทำเช่นนั้นชุด คุณอาจต้องการอ่านคู่มือเกี่ยวกับ bcสำหรับรายละเอียดเพิ่มเติม
Bill Karwin

186

พยายามprintf(1)?

printf "%x\n" 34
22

อาจมีหลายวิธีในการทำเช่นนั้นด้วยฟังก์ชัน builtin ในเชลล์ทั้งหมด แต่จะพกพาได้น้อยกว่า ฉันไม่ได้ตรวจสอบข้อกำหนด POSIX sh เพื่อดูว่ามีความสามารถดังกล่าวหรือไม่


5
มันไม่ได้ POSIX มากไปกว่า printf สิ่งนี้ใช้ได้แม้ใน "sh"
Orwellophile

4
printf ไม่ใช่ความแม่นยำตามลักษณะ bcคือ. ตัวอย่างเช่นการ238862874857408875879219909679752457540ป้อนข้อมูล printf ทำให้เรามี "ผลลัพธ์ใหญ่เกินไป" วิธี BC ใช้งานได้ดีสำหรับสิ่งที่ใหญ่กว่ามาตรฐาน int / long / bigint
Andrew Backer

3
และถ้าคุณต้องการตัวพิมพ์ใหญ่เป็นprintf "%X"
เลข

3
และหากต้องการบังคับให้เอาต์พุตเช่น "0x00" คุณสามารถใช้ printf "0x% 02X" ได้
gbetous

1
... และbcไม่สามารถใช้งานได้ทุกที่ (อย่างน้อยก็ไม่ใช่ใน Linux ที่ฝังไว้ของฉัน)
Matthieu

69

เลขฐานสิบหกถึงทศนิยม:

$ echo $((0xfee10000))
4276158464

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

$ 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 VARเป็นส่วนขยาย bash ไม่ได้กล่าวถึงในหน้าคนเปิดเผยเฉพาะในกรณีที่มีการโทรprintfโดยไม่มีข้อโต้แย้ง
Adrian W

5

ขออภัยความผิดของฉันลองสิ่งนี้ ...

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

ตัวอย่าง:

$ ./dtoh 1024
400

1
ขอบคุณสิ่งนี้ช่วยได้มากสำหรับ env ที่ไหนprintfและhexคำสั่งไม่พร้อมใช้งาน
benchuk

2
@benchuk printfไม่มีจำหน่ายที่ไหน
Matthieu


3

ในzshที่คุณสามารถทำเรียงของสิ่งนี้:

% typeset -i 16 y
% print $(( [#8] x = 32, y = 32 ))
8#40
% print $x $y
8#40 16#20
% setopt c_bases
% print $y
0x20

ตัวอย่างที่นำมาจากหน้าเอกสารเกี่ยวกับเลขคณิตประเมินผลzsh

ฉันเชื่อว่า Bash มีความสามารถที่คล้ายกัน


2

ในกรณีของฉันฉันพบปัญหาหนึ่งเกี่ยวกับการใช้โซลูชัน printf:

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

วิธีที่ง่ายที่สุดคือการใช้โซลูชันกับbcซึ่งแนะนำในโพสต์ที่สูงกว่า:

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


โซลูชันของคุณเพิ่มอะไรในสิ่งที่เขียนเมื่อหลายปีก่อน
Matthieu

1
@ Matthieu กล่าวถึงปัญหาของตัวเลขที่มีเลขศูนย์นำหน้าซึ่ง Bash printf ตีความว่าเป็นเลขฐานแปดอย่างไม่เป็นประโยชน์และแสดงวิธีแก้ปัญหาที่หลีกเลี่ยงปัญหา
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

นี่ไม่ใช่เชลล์สคริปต์ แต่เป็นเครื่องมือ cli ที่ฉันใช้เพื่อแปลงตัวเลขระหว่าง 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);
    }
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.