Перетворити десятковий у шістнадцятковий у скрипті оболонки UNIX


110

У скрипті оболонки UNIX, що я можу використовувати для перетворення десяткових чисел у шістнадцятковий? Я думав, що Од зробить трюк, але це не зрозуміє, що я його подаю ASCII уявленням чисел.

printf? Валовий! Використовуйте його наразі, але що ще є?


8
Я мушу запитати, що ж таке грубо з printf? Багато поширених мов програмування підтримують форматування, подібне до формату printf, тому розробники printf нижче, безумовно, будуть найпростішими для розуміння розробниками.
Майкл Шепер

4
Хлопчик, я не знаю - це було п’ять років тому! Я думаю, може, я думав, що це не справжня оболонка чи щось таке.
skiphoppy

Відповіді:


108
echo "obase=16; 34" | bc

Якщо ви хочете відфільтрувати цілий файл цілих чисел, по одному на рядок:

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

1
Я переглянув і bc (1), і dc (1), і пропустив цей.
Келтія

3
@skiphoppy: Якщо ви пишете: echo "obase = 16; 12 34 56" | bc ви отримуєте 1E240, точно так само, як якщо б ви написали: echo "obase = 16; 123456" | до н.е. Тож спосіб розібратися з довільними числами цілих чисел у одному рядку - це поставити кожне число у свій рядок: tr '' '\ 015' <вхід | bc (карта пробілів до нових рядків).
Джонатан Леффлер

1
Це чудово, якщо у вас є "bc", але "printf" є частиною самого bash
fuzzyTew

1
@Bill Karwin, або zsh, або busybox, але, можливо, не якась оболонка, яку я не пробував? Я більше не встановлюю звичайний ш, але чітко skiphoppy шукає, які інші варіанти є
fuzzyTew

2
@ Шрідхара-Sarnobat, це є десяткової в шістнадцяткову. Я припускаю, що ви маєте на увазі конвертувати шістнадцятковий у dec. Для цього встановіть ibase=16. Ви можете прочитати посібник на bc для отримання більш детальної інформації.
Білл Карвін

186

Пробували printf(1)?

printf "%x\n" 34
22

Ймовірно, є способи зробити це з вбудованими функціями у всіх оболонках, але це було б менш портативно. Я не перевіряв специфікації POSIX sh, щоб побачити, чи має він такі можливості.


5
Це не набагато більше POSIX, ніж printf. Це навіть працює в "ш".
Орвелофіл

4
printf - не атрибутна точність. bcє. наприклад, беручи 238862874857408875879219909679752457540за вхід, printf дає нам "Результат занадто великий". метод BC ідеально підходить для речей, більших за стандартний int / long / bigint
Ендрю Бекер

3
І, якщо ви хочете, щоб великі літери були шістнадцятковими, скористайтеся printf "%X"великими літерами X.
andrybak

3
А щоб примусити вихід, наприклад "0x00", ви можете використовувати printf "0x% 02X"
вигадливий

1
... і bcдоступний не скрізь (принаймні, не в моєму вбудованому Linux).
Матьє

69

Шестнадцятковий до десяткових:

$ echo $((0xfee10000))
4276158464

Десятичний до шістнадцяткової:

$ printf '%x\n' 26
1a


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команди недоступні.
бенчук

2
@benchuk де printfнедоступний?
Матьє



2

У моєму випадку я натрапив на одну проблему із використанням рішення printf:

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

Найпростішим способом було використання рішення з bc , запропонованого в пост вище:

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


Що ваше рішення додає до тих, що були написані роками раніше?
Матьє

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);
    }
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.