在 Bash 中,如何从十进制进行基数转换到另一个基数,尤其是十六进制。走另一条路似乎很容易:
$ echo $((16#55))
85
通过网络搜索,我找到了一个可以进行数学和字符操作来进行转换的脚本,我可以将其用作函数,但我认为 bash 已经有一个内置的基数转换了——可以?
答案1
使用bash
(或任何 shell,前提是该printf
命令可用(通常在 shell 中内置的标准 POSIX 命令)):
printf '%x\n' 85
使用zsh
,您还可以执行以下操作:
dec=85
hex=$(([##16]dec))
这适用于 2 到 36 的基数(0-9a-z
数字不区分大小写)。
$(([#16]dev))
如果启用该选项,(只有一个#
)将扩展为16#55
or 0x55
(作为基数 16 的特殊情况) (如果也启用了该cbases
选项,也适用于基数 8(0125
而不是) )。8#125
octalzeroes
通过ksh93
,您可以使用:
dec=85
base54=${ printf %..54 "$dec"; }
适用于 2 到 64 的碱基(与0-9a-zA-Z@_
数字一样)。
有了ksh
和zsh
,还有:
$ typeset -i34 x=123; echo "$x"
34#3l
尽管 ksh88、zsh 和 pdksh 中的碱基数最多为 36 个,ksh93 中的碱基数最多为 64 个。
long
请注意,所有这些都仅限于系统上整数的大小(int
对于某些 shell)。对于更大的东西,您可以使用bc
或dc
。
$ echo 'obase=16; 9999999999999999999999' | bc
21E19E0C9BAB23FFFFF
$ echo '16o 9999999999999999999999 p' | dc
21E19E0C9BAB23FFFFF
支持的基数范围从 2 到 POSIX 要求的至少为 99 的某个数字。对于大于 16 的基数,大于 9 的数字表示为以空格分隔的 0 填充的十进制数。
$ echo 'obase=30; 123456' | bc
04 17 05 06
或者与dc
(bc
曾经是(并且仍然在某些系统上)包装器相同dc
):
$ echo 30o123456p | dc
04 17 05 06
答案2
使用 printf:
$ printf "%d %x\n" $((16#55)) $((10#85))
85 55
要将值分配给变量,请使用命令替换:
$ x=$( printf "%x" 85 ) ; echo $x
55
答案3
使用所有 POSIX 兼容 shell 中存在的内置算术扩展替换 - 这在当今几乎是普遍的。
$ echo $((0xbc))
188
和
$ hex=dead
$ dec=$((0x$hex))
$ echo $dec
57005
注意:特别是在最后一个示例中,扩展可能会导致意外结果 - 变量“hex”中的十六进制数字必须形成合法的十六进制常量,否则可能会发生模糊的错误消息。例如,如果“hex”为“0xdead”,则算术扩展将变为 0x0xdead,这不能解释为常量。当然,在这种情况下,算术扩展 $(($hex)) 就可以解决问题。留给读者的练习是创建简单的子字符串处理模式匹配,以删除可选的“0x”前缀。
答案4
您可以使用 awk丝绒库:
$ velour -n 'print n_baseconv(15, 10, 16)'
F
或者:
$ velour -n 'print n_baseconv(ARGV[1], 10, 16)' 15
F