xiaobaoqiu Blog

Think More, Code Less

Linux进制转换

经常涉及到进制的转换,比如线上处理问题时候经常需要转换线程id到16进制.

1.进制转换

2.1.shell运算

Shell 运算把一个数字从给定的进制转换位十进制.如果数字以运算展开式的形式提供,那么假定它带有十进制符号,除非 它前面带有 0(这种情况假定是八进制)或 0x(这种情况假定是十六进制)

1
2
3
4
xiaobaoqiu@xiaobaoqiu:~/myshell$ echo $((010))
8
xiaobaoqiu@xiaobaoqiu:~/myshell$ echo $((0x10))
16

也可以指定 2 到 64 之间的任意进制,超过64进制则不支持.格式如下:

1
$((BASE#NUMBER))

使用举例如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
xiaobaoqiu@xiaobaoqiu:~/myshell$ echo $((2#10))
2
xiaobaoqiu@xiaobaoqiu:~/myshell$ echo $((5#10))
5
xiaobaoqiu@xiaobaoqiu:~/myshell$ echo $((8#10))
8
xiaobaoqiu@xiaobaoqiu:~/myshell$ echo $((10#10))
10
xiaobaoqiu@xiaobaoqiu:~/myshell$ echo $((16#10))
16
xiaobaoqiu@xiaobaoqiu:~/myshell$ echo $((64#10))
64
xiaobaoqiu@xiaobaoqiu:~/myshell$ echo $((100#10))
bash: 100#10: 无效的算数进制 (错误符号是 "100#10")

2.2.bc

bc是一种任意精度运算语言,大多数 UNIX/Linux 安装程序都提供.因为它允许您指定输出进制,所以当您需要以十进制以外的进制输出时,这是一种很好的技术.

bc 的特殊变量 ibase 和 obase 分别包含用于输入和输出的进制的值.缺省情况下,都被设置为 10.要执行进制转换,需要改变其中的一个或两个值,然后提供一个数字.

1
2
3
4
5
6
xiaobaoqiu@xiaobaoqiu:~/myshell$ echo 'obase=16; 10' | bc
A
xiaobaoqiu@xiaobaoqiu:~/myshell$ echo 'obase=16; ibase=10; 10' | bc
A
xiaobaoqiu@xiaobaoqiu:~/myshell$ echo 'obase=10; ibase=16; 10' | bc
16

2.3.printf

格式化参数和C语言的格式一致:

1
2
3
4
xiaobaoqiu@xiaobaoqiu:~/myshell$ printf "%X\n" 100
64
xiaobaoqiu@xiaobaoqiu:~/myshell$ printf "%d\n" 0x10
16

2.自定义shell

自己写一个shell,处理多个输入,任意进制到任意进制的转换.通过这个脚本,学习了一下shell处理option的方式.

原理很简单,就是利用上面说道的bc命令.shell脚本如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
#!/bin/bash
while getopts :i:o: opt 
do
        case "$opt" in
        i) #输入的参数的进制
           #echo "Found the -i option,with vale $OPTARG"
           ibase=$OPTARG
           ;;
        o) #输出参数进制
           #echo "Found the -o option,with vale $OPTARG"
           obase=$OPTARG
           ;;
        *) #当有不认识的选项的时候arg为?
           echo "unkonw argument, Usage : "
           echo "$1 -i 10 -o 16 1 2 3 4 5 6 ..."
           exit 1
        esac
done

#跳过opt参数
shift $[$OPTIND - 1]

#参数检验
if [ ! $ibase ]; then
    echo "Usage : $0 -i 10 -o 16 1 2 3 4 5 6 ..."
    exit 1
fi

if [ ! $obase ]; then
    echo "Usage : $0 -i 10 -o 16 1 2 3 4 5 6 ..."
    exit 1
fi

echo "输入进制:$ibase"
echo "输出进制:$obase"

#执行进制转换
for i in $@
do
    echo "obase=$obase; ibase=$ibase; $i" |bc
done

1.bc

2.bc

简单使用如下:

1
2
3
4
xiaobaoqiu@xiaobaoqiu:~/myshell$ ./trans -i 10 -o 16 100
输入进制:10
输出进制:16
64