我是@程序员小助手Rman,仅次于Xman,Ironman,Superman。
引言
Bash编程中,我们一般不需要把字符串格式化为十六进制。因为,十进制是给人类看的,而16进制则用于存储到计算机。
本文通过编程实践中所遇到的困难,引出进制转换的问题。然后给出解决方案。其中,格式化字符串,所用的元字符非常有用。
问题
有一个小哥在编程过程中,产生了一个疑问,他说,把十六进制的数值转换为十进制,似乎很容易。只用下面这个公式。
echo $((16#55))
输出为 85。
那么问题来了。如果反向操作该怎么办呢?
方案
使用bash,或任何shell,通畅都提供了 printf 方法,这是在shell中构建的标准POSIX命令。
只需运行下面这个函数,
printf '%x\n' 85
输出内容 55。
在 zsh 中你可以这么写:
dec=85
hex=$(([##16]dec))
这种方法,对于2-36的基数,都是有效的。不过数位支持0-9a-z这些字符罢了。
在 ksh93 中你可以这么写:
dec=85
base54=$(printf %..54 "$dec")
这个支持的基数更大,从2-64,支持的字符也就多了 0-9a-zA-Z@_。
在 ksh,zsh中,还能这么写:
typeset -i34 x=123; echo "$x"
这个是把十进制数123转换为基数为34的值,结果输出 34#31。
有个事儿你得多注意,这些转换是有限制的,比如 ksh88, zsh and pdksh 基数支持到36,ksh93支持到64。
那么对于更大的数,怎么转换呢?这就需要用到 bc / dc 程序。
比如一个超长的数儿,发送解析式到 bc :
echo 'obase=16; 9999999999999999999999' | bc
转换为16进制,结果为 21E19E0C9BAB23FFFFF。
当然也可以使用 dc 程序:
echo '16o 9999999999999999999999 p' | dc
结果是一样的,就不再贴出来了。
bc / dc 程序支持的基数从2到POSIX支持的数字,至少可达到99。对于大于16的基数,大于9的数字用空格分隔,由0前导填充的数表示。
echo 'obase=30; 123456' | bc
输出内容是这样的
04 17 05 06
使用 dc 的结果一样,请注意中间的空格,和前导0的填充。
写在最后
好吧,问1得10,夫复何求。连各种shell的差别都讲了,还有比这更用心的吗?
Happy coding :)
领取专属 10元无门槛券
私享最新 技术干货