Shell 脚本中的十六进制到十进制

有人能帮我在 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 "-")
206088 次浏览

要将十六进制转换为十进制,有许多方法可以在 shell 中或通过外部程序实现:

:

$ 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

您可以在 shell 中使用各种工具。根据你最初的问题,斯普特尼克已经给了你一个很好的选择概述。他花了那么多时间给你们正确答案他绝对值得投票。

还有一件事不在他的清单上:

[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 ——一个随机的十六进制数字,我从你的初始数字中减去
  • - ——获取我们推出的两个数字,从前一个数字中减去后一个数字,然后将结果推回到堆栈中
  • 打印堆栈上的最后一项。这不会改变堆栈,所以..。
  • 10o ——告诉 dc 以基数“10”打印输出,但请记住,我们的输入编号目前是十六进制,因此“10”表示“16”。
  • 再次打印堆栈上的最后一项... 这次是十六进制。

你可以用直流电构造极其复杂的数学解。在您的 shell 脚本工具箱中有这样一个好东西。

还有一种使用 shell 的方法(bash 或 ksh,不适用于 ash) :

echo $((16#FF))
255

在 Linux 上处理一个非常轻量级的 busybox 嵌入版本意味着许多传统命令不可用(bc、 printf、 dc、 perl、 python)

echo $((0x2f))
47


hexNum=2f
echo $((0x${hexNum}))
47

这个解决方案归功于 Peter Leung

当变量为 null (或空)时,出现报告的错误:

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

这可能是因为给予 bc 的值不正确。这很可能是因为 bc 需要 UPPERcase 值。它需要 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)的整数。这将是唯一的区别与公元前没有这样的限制。

在破折号和其他 shell 中,可以使用

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

将十六进制数转换为十进制数。 这不是 bash 或 ksh 特有的。

目前最短的路线:

$ 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