UNIX kabuk komut dosyasında ondalıklıyı onaltılıya dönüştürme


110

Bir UNIX kabuk komut dosyasında, ondalık sayıları onaltılık tabana dönüştürmek için ne kullanabilirim? İşe yarayacağını düşünmüştüm, ama onu sayıların ASCII temsilleriyle beslediğimi fark etmiyor.

Printf? Brüt! Şimdilik kullanıyorum, ama başka ne var?


8
Printf'in nesi iğrenç diye sormalıyım? Birçok yaygın programlama dili, printf benzeri biçimlendirmeyi destekler, bu nedenle aşağıdaki printf çözümleri, geliştiricilerin anlaması kesinlikle en kolay çözüm olacaktır.
Michael Scheper

4
Oğlum, bilmiyorum - bu beş yıl önceydi! Sanırım bunun gerçek kabuk falan olmadığını düşündüm.
2013 saat

Yanıtlar:


108
echo "obase=16; 34" | bc

Tam sayılardan oluşan bir dosyanın tamamını, her satıra bir tane olacak şekilde filtrelemek istiyorsanız:

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

1
Hem bc (1) hem de dc (1) 'e baktım ve bunu kaçırdım.
Keltia

3
@skiphoppy: Yazarsanız: echo "obase = 16; 12 34 56" | bc yazdığınız gibi 1E240 elde edersiniz: echo "obase = 16; 123456" | M.Ö. Bu nedenle, tek bir satırda rastgele sayılarla başa çıkmanın yolu, her sayıyı kendi satırına koymaktır: tr '' '\ 015' <input | bc (boşlukları yeni satırlarla eşleyin).
Jonathan Leffler

1
Eğer '
bc'ye

1
@ Bill Karwin veya zsh veya busybox, ama belki denemediğim bir kabuk değil mi? Artık düz sh'yi yüklü tutmuyorum ama açıkça skiphoppy başka hangi seçeneklerin olduğunu arıyor
fuzzyTew

2
Sridhar-Sarnobat @, bu ise onaltılıya ondalık. Hex'i dec'e dönüştürmek demek istediğinizi varsayıyorum. Bunu yapmak için ayarlayın ibase=16. Daha fazla ayrıntı için bc'deki kılavuzu okumak isteyebilirsiniz .
Bill Karwin

186

Denedin printf(1)mi?

printf "%x\n" 34
22

Muhtemelen tüm kabuklarda yerleşik işlevlerle bunu yapmanın yolları vardır, ancak daha az taşınabilir olacaktır. Bu tür yeteneklere sahip olup olmadığını görmek için POSIX sh özelliklerini kontrol etmedim.


5
Printf'den çok daha fazla POSIX almaz. Bu "sh" de bile çalışır.
Orwellophile

4
printf keyfi bir kesinlik değildir. bcdır-dir. örneğin, 238862874857408875879219909679752457540girdi olarak alındığında printf bize "Sonuç çok büyük" verir. BC yöntemi, standart bir int / long / bigint'den daha büyük şeyler için harika çalışıyor
Andrew Backer

3
Ve onaltılık büyük harf istiyorsanız, büyük harf printf "%X"X kullanın .
andrybak

3
Ve "0x00" gibi bir çıktıyı zorlamak için printf "0x% 02X" kullanabilirsiniz
gbetous

1
... ve bcher yerde mevcut değil (en azından gömülü Linux'umda değil).
Matthieu

69

Onaltılıktan ondalığa:

$ echo $((0xfee10000))
4276158464

Ondalıktan onaltılıya:

$ 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 VARbir bash uzantısıdır. Man sayfasında bahsedilmemiş , sadece printftartışmasız
Adrian W

5

Üzgünüm benim hatam, bunu dene ...

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

Misal:

$ ./dtoh 1024
400

1
Teşekkürler bu ortam için çok yardımcı oldu. nerede printfve hexkomutlar mevcut değildir.
benchuk

2
@benchuk nerede mevcut printfdeğil?
Matthieu



2

Benim durumumda, printf çözümünü kullanırken bir sorunla karşılaştım:

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

En kolay yol, daha yüksek yazıda önerilen bc ile çözümü kullanmaktı :

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


Çözümünüz yıllar önce yazılanlara ne katıyor?
Matthieu

1
@Matthieu Bash printf'in yararsız bir şekilde sekizlik olarak yorumladığı önde gelen sıfırlarla sayılar konusundan bahseder ve sorunu önleyen bir çözüm gösterir.
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

Bu bir kabuk betiği değil, ancak sayıları bin / oct / dec / hex arasında dönüştürmek için kullandığım cli aracı:

    #!/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);
    }
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.