Шестнадцатеричный в десятичный в сценарии оболочки


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 郝海东 冠状 病 六四 事件 法轮功

Ответы:


314

Чтобы преобразовать шестнадцатеричный формат в десятичный, есть много способов сделать это в оболочке или с помощью внешней программы:

С участием :

$ 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 07

10
Так что ? Это как раз цель моих 4 команд, прежде чем вы измените смысл своего вопроса.
Gilles Quenot 07

2
Является ли printfрешение POSIX? Если да, то это лучшее :)
Чиро Сантилли 郝海东 冠状 病 六四 事件 法轮功

3
В bash вы также можете использовать $((0xff)), т.е. с шестнадцатеричным префиксом, подобным C, вместо 16#, хотя N#это явно более общий вариант.
Руслан

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

Благодарим Питера Люнга за это решение.


1
Хорошо, но остерегайтесь ошибки переполнения целого числа, например, echo $((0x077E9F2DBF49D100001))превышение предела 64-битного целого числа 2 ^ 64. bcобрабатывает это правильно
roblogic

13

Еще один способ сделать это с помощью оболочки (bash или ksh, не работает с тире):

echo $((16#FF))
255

Что означает #символ? Есть ли другие приложения или документация, чтобы узнать больше о его использовании?
user1527227 02

1
Здесь упоминается: ссылка . В конце раздела 6.5 говорится: «... числа принимают форму [base #] n, где необязательная база - это десятичное число от 2 до 64, представляющее арифметическое основание, а n - это число в этой базе. Если base # опускается, тогда используется основание 10. Цифры больше 9 представлены строчными буквами, прописными буквами, '@' и '_' в указанном порядке. Если base меньше или равно 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- «настольный расчет». Он также будет принимать входные данные со стандартного ввода, например bc, но вместо использования «порядка операций» он использует нотацию стекирования («обратную польскую»). Вы даете ему входные данные, которые он добавляет в стек, затем даете ему операторы, которые выталкивают элементы из стека и возвращают результаты.

В приведенных выше командах мы получили следующее:

  • 16i- сообщает DC принимать ввод с основанием 16 (шестнадцатеричный). Не меняет базу выпуска.
  • BFCA3000 - ваш начальный номер
  • 17FF - случайное шестнадцатеричное число, которое я выбрал для вычитания из вашего начального числа
  • - - возьмите два числа, которые мы вставили, и вычтите последнее из более раннего, затем поместите результат обратно в стек
  • p- распечатать последний элемент в стопке. Это не меняет стек, так что ...
  • 10o - указывает dc печатать свой вывод в базе «10», но помните, что наша схема нумерации входных данных в настоящее время шестнадцатеричная, поэтому «10» означает «16».
  • p - снова распечатать последний элемент в стопке ... на этот раз в шестнадцатеричном формате.

Вы можете создавать невероятно сложные математические решения с помощью постоянного тока. Это хорошо, если в вашем наборе инструментов есть сценарии оболочки.


3

Сообщение об ошибке появляется, когда переменные имеют значение NULL (или пустые):

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

Это могло произойти из-за неправильного значения bc. Вполне может быть, что bc нужны значения ВЕРХНЕГО регистра. Необходимо 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

В dash и других оболочках вы можете использовать

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

для преобразования шестнадцатеричного числа в десятичное. Это не относится к bash или ksh.


1
egprintf "%d" 0xff
lashgar
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.