bash 在shell脚本中将十进制数转换为十六进制和二进制
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/18870209/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Convert a decimal number to hexadecimal and binary in a shell script
提问by splinux
I have a decimal number in each line of a file.txt
:
我在 a 的每一行都有一个十进制数file.txt
:
1
2
3
I am trying (for too long now) to write a one-liner script to have an output where each row has a column with the decimal, hexadecimal and the binary. To ease the task we can say that the original number is expressed in a byte. So the maximum value is 255.
我正在尝试(现在太久)编写一个单行脚本来输出,其中每一行都有一个包含十进制、十六进制和二进制的列。为了简化任务,我们可以说原始数字以字节表示。所以最大值是 255。
I first try to decode each number as a bynary with prepended 0 so to have an 8 bits pattern:
awk '{print "ibase=10;obase=2;" $1}' $1 | bc | xargs printf "%08d\n"
where the outer $1 in the awk statement is
file.txt
. The output is :00000001 00000010 00000011
Same for hex with one prepended 0
awk '{printf("0x%02x\n", $1)}' $1
Same as before. The Output is :
0x01 0x02 0x03
Well, the decimal should be just a print:
1 2 3
我首先尝试将每个数字解码为一个带有 0 的二进制数,以便有一个 8 位模式:
awk '{print "ibase=10;obase=2;" $1}' $1 | bc | xargs printf "%08d\n"
awk 语句中外部的 $1 是
file.txt
. 输出是:00000001 00000010 00000011
十六进制相同,前面加一个 0
awk '{printf("0x%02x\n", $1)}' $1
和之前一样。输出是:
0x01 0x02 0x03
好吧,小数应该只是一个打印:
1 2 3
What I'd like to have is one liner where I have:
我想要的是一个班轮,我有:
1 00000001 0x01
2 00000001 0x02
so basically to put 1. 2. and 3. in each line of the output.
所以基本上把 1. 2. 和 3. 放在输出的每一行中。
I tried to execute bc (and other command) within awk using system() without success. And a zillion other ways. What is the way you would do it?
我尝试使用 system() 在 awk 中执行 bc(和其他命令)但没有成功。还有无数其他方式。你会怎么做?
回答by dogbane
The following one-liner should work:
以下单行应该工作:
printf "%s %08d 0x%02x\n" "" $(bc <<< "ibase=10;obase=2;") ""
Example output:
示例输出:
$ for i in {1..10}; do printf "%s %08d 0x%02x\n" "$i" $(bc <<< "ibase=10;obase=2;$i") "$i"; done
1 00000001 0x01
2 00000010 0x02
3 00000011 0x03
4 00000100 0x04
5 00000101 0x05
6 00000110 0x06
7 00000111 0x07
8 00001000 0x08
9 00001001 0x09
10 00001010 0x0a
回答by Gunstick
So I searched for a short and elegant awk binary converter. Not satisfied considered this as a challenge, so here you are. A little bit optimzed for size, so I put a readable version below.
所以我搜索了一个简短而优雅的 awk 二进制转换器。不满意认为这是一个挑战,所以你来了。稍微优化了大小,所以我在下面放了一个可读的版本。
The printf at the end specifies how large the numbers should be. In this case 8 bits.
最后的 printf 指定数字应该有多大。在本例中为 8 位。
Is this bad code? Hmm, yeah... it's awk :-) Does of course not work with very huge numbers.
这是坏代码吗?嗯,是的......这是 awk :-) 当然不适用于非常大的数字。
67 characters long awk code:
67 个字符长的 awk 代码:
awk '{r="";a=;while(a){r=((a%2)?"1":"0")r;a=int(a/2)}printf"%08d\n",r}'
Edit: 55 characters awk code
编辑:55 个字符的 awk 代码
awk '{r="";a=;while(a){r=a%2r;a=int(a/2)}printf"%08d\n",r}'
Readable version:
可读版本:
awk '{r="" # initialize result to empty (not 0)
a= # get the number
while(a!=0){ # as long as number still has a value
r=((a%2)?"1":"0") r # prepend the modulos2 to the result
a=int(a/2) # shift right (integer division by 2)
}
printf "%08d\n",r # print result with fixed width
}'
And the asked one liner with bin and hex
并询问了一个带垃圾箱和六角形的衬垫
awk '{r="";a=;while(a){r=a%2r;a=int(a/2)}printf"%08d 0x%02x\n",r,}'
回答by cnicutar
You don't need bc
. Here's a solution using only awk:
你不需要bc
. 这是仅使用 awk 的解决方案:
- Fetch the
bits2str
function available in the manual Add this minimal script:
{ printf("%s %s %x\n", , bits2str(), ) }
- 获取手册中可用的
bits2str
函数 添加这个最小脚本:
{ printf("%s %s %x\n", , bits2str(), ) }
This produces:
这产生:
$ awk -f awkscr.awk nums
1 00000001 1
2 00000010 2
3 00000011 3