有人可以帮我在 shell 脚本中将十六进制数转换为十进制数吗?
例如,我想使用 shell 脚本将十六进制数
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 "-")
要从十六进制转换为十进制,有很多方法可以在 shell 中或使用外部程序来完成:
与bash:
$ echo $((16#FF))
255
与bc:
$ echo "ibase=16; FF" | bc
255
与perl:
$ perl -le 'print hex("FF");'
255
与printf:
$ printf "%d\n" 0xFF
255
与python:
$ python -c 'print(int("FF", 16))'
255
与红宝石:
$ ruby -e 'p "FF".to_i(16)'
255
与node.js:
$ node -e "console.log(parseInt('FF', 16))"
255
与犀牛:
$ rhino -e "print(parseInt('FF', 16))"
255
与groovy:
$ groovy -e 'println Integer.parseInt("FF",16)'
255
在 Linux 上处理非常轻量级的嵌入式 busybox 版本意味着许多传统命令不可用(bc、printf、dc、perl、python)
echo $((0x2f))
47
hexNum=2f
echo $((0x${hexNum}))
47
此解决方案归功于 Peter Leung。
另一种使用 shell 的方法(bash 或 ksh,不适用于破折号):
echo $((16#FF))
255
您可以在 shell 中使用各种工具。根据您最初的问题,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
命令是“桌面计算”。它还将从 stdin 获取输入,如bc
,但它不使用“操作顺序”,而是使用堆栈(“反向波兰语”)表示法。你给它添加到堆栈的输入,然后给它操作符,从堆栈中弹出项目,然后推回结果。
在上面的命令中,我们有以下内容:
16i
——告诉 dc 接受以 16 为基数(十六进制)的输入。不改变输出基础。BFCA3000
-- 你的初始号码17FF
——我选择从你的初始数字中减去的随机十六进制数-
-- 取我们压入的两个数字,用前面的数字减去后面的数字,然后将结果推回堆栈p
-- 打印堆栈中的最后一项。这不会改变堆栈,所以...10o
-- 告诉 dc 以“10”为基数打印其输出,但请记住我们的输入编号方案目前是十六进制的,因此“10”表示“16”。p
-- 再次打印堆栈中的最后一项......这次是十六进制。您可以使用 dc 构建极其复杂的数学解决方案。在您的 shell 脚本工具箱中拥有它是一件好事。
在 dash 和其他 shell 中,你可以使用
printf "%d\n" (your hexadecimal number)
将十六进制数转换为十进制数。 这不是 bash 或 ksh 特有的。
当变量为空(或空)时出现报告的错误:
$ 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 计算的。如果以 64 位编译,Bash 仅限于小于 ((2**63)-1) 的整数。这将是与没有这种限制的 bc 的唯一区别。
最短的路:
$ echo $[0x3F]
63
我的 $PATH 上有这个方便的脚本来过滤
0x1337
-like; 1337
;或 "0x1337"
行输入到十进制字符串(为清楚起见进行了扩展):
#!/usr/bin/env bash
while read data; do
withoutQuotes=`echo ${data} | sed s/\"//g`
without0x=`echo ${withoutQuotes} | sed s/0x//g`
clean=${without0x}
echo $((16#${clean}))
done