bash 添加两个十六进制数并在 shell 脚本中存储为十六进制数
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/24019361/
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
Add two hex numbers and store as hex number in shell script
提问by akhil28288
I am trying to add two hex numbers in a shell script and store the result as a hex number.
我正在尝试在 shell 脚本中添加两个十六进制数并将结果存储为十六进制数。
let "step_size = 10"
let "start_num = 20000000"
let "size = 64"
for (( i = 0; i < 1000; i = $i + $step_size ))
do
for (( j = 0; j < $step_size; j++ ))
do
let "temp = $(( $(( $i * $step_size)) + $(( $j * $size )) ))"
num=`echo "obase=16; $temp" | bc`
echo $num
num2=`obase=16;ibase=16; echo $start_num \+ $num | bc`
echo $start_num $num $num2
echo "****"
done
done
Not all results are wrong. I get an error only when $num = C0
并非所有结果都是错误的。仅当我收到错误$num = C0
Output
输出
0
20000000 0 20000000
****
40
20000000 40 20000040
****
80
20000000 80 20000080
****
C0
20000000 C0 20000090 #This is the error!!
****
100
20000000 100 20000100
****
...
...
...
1C0
20000000 1C0 20000190 #Error again!!
I am using zshell. I am not sure why this is happening. Any help is highly appreciated.
我正在使用 zshell。我不确定为什么会这样。任何帮助都受到高度赞赏。
Thanks
谢谢
采纳答案by konsolebox
Probably
大概
num2=`obase=16;ibase=16; echo $start_num \+ $num | bc`
should be
应该
num2=`echo "obase=16;ibase=16;$start_num + $num" | bc`
You weren't calculating hex at all.
你根本没有计算十六进制。
I also suggest a simpified version like this:
我还建议一个像这样的简化版本:
#!/bin/zsh
step_size=10
start_num=20000000
size=64
for (( i = 0; i < 1000; i += step_size )); do
for (( j = 0; j < step_size; ++j )); do
(( temp = (i * step_size) + (j * size) ))
num=$(echo "obase=16; $temp" | bc)
echo "$num"
num2=$(echo "obase=16;ibase=16;$start_num + $num" | bc)
echo "$start_num $num $num2"
echo "****"
done
done
And it works both in Zsh and Bash.
它适用于 Zsh 和 Bash。
# bash temp.zsh | head -20
0
20000000 0 20000000
****
40
20000000 40 20000040
****
80
20000000 80 20000080
****
C0
20000000 C0 200000C0
****
100
20000000 100 20000100
****
140
20000000 140 20000140
****
180
20000000 180 20000180
回答by rici
@konsolebox has a correct fix, but I think the behaviour shown in the OP is a bit mysterious, so it seems to be worth an explanation.
@konsolebox 有一个正确的修复,但我认为 OP 中显示的行为有点神秘,所以似乎值得解释一下。
First, it's clear that
首先,很明显
num2=`obase=16;ibase=16; echo $start_num \+ $num | bc`
is incorrect because it is setting the shell variables obase
and ibase
rather than passing the assignment to bc
. Also, it's unnecessary to quote the +. But why doesn't bc
produce an error from the \, as it would if the line had been written in the modern form:
不正确,因为它是设置shell变量obase
和ibase
而不是传递分配bc
。此外,没有必要引用+. 但是为什么不bc
从 产生错误\,就像该行以现代形式编写的那样:
num2=$(obase=16;ibase=16; echo $start_num \+ $num | bc)
The answer is that there is a subtle difference between `…`
and $(…)
:
答案是`…`
和之间存在细微差别$(…)
:
% `echo echo \+`
+
% $(echo echo \+)
\+
Quoting the bash
manual:
引用bash
手册:
When the old-style backquote form of substitution is used, backslash retains its literal meaning except when followed by $, `, or \. The first backquote not preceded by a backslash terminates the command substitution. When using the
$(command)
form, all characters between the parentheses make up the command; none are treated specially.
当使用旧式反引号替换形式时,反斜杠保留其字面含义,除非后跟$, `, 或\。前面没有反斜杠的第一个反引号终止命令替换。使用
$(command)
表格时,括号内的所有字符组成命令;没有被特殊对待。
In effect, that means that the backquote-version interprets the \
-escape twice: first when the backquoted string is scanned, when \\+
becomes \+
, and then a second time when the resulting command is parsed, when \+
becomes +
.
实际上,这意味着反引号版本会解释\
-escape 两次:第一次是在扫描反引号字符串时,当\\+
变成 时\+
,第二次是在解析结果命令时,当\+
变成 时+
。
The second question is "where did 20000090 come from?" And here the answer is that it is a curious feature of the way bc
interprets numbers. It's worth quoting the full paragraph from man bc
(emphasis added):
第二个问题是“20000090从哪里来?” 答案是,这是bc
解释数字方式的一个奇怪特征。值得引用完整的段落man bc
(强调添加):
Input numbers may contain the characters
0-9
andA-F
. (Note: They must be capitals. Lower case letters are variable names.) Single digit numbers always have the value of the digit regardless of the value ofibase
. (i.e.A = 10
.) For multi-digit numbers,bc
changes all input digits greater or equal toibase
to the value ofibase-1
.This makes the numberFFF
always be the largest 3 digit number of the input base.
输入数字可能包含字符
0-9
和A-F
。(注意:它们必须是大写的。小写字母是变量名。)无论 的值如何,单个数字始终具有该数字的值ibase
。(即A = 10
。) 对于多位数字,bc
将所有输入数字更改为大于或等于ibase
的值ibase-1
。这使得数字FFF
始终是输入基数的最大 3 位数字。
Since ibase
was not set in bc
(see above), bc
interprets C0
as decimal 90
, although it would have interpreted C
as decimal 12
.
由于ibase
未设置bc
(见上文),bc
解释C0
为 decimal 90
,尽管它会解释C
为 decimal 12
。
Finally, with either bash
or zsh
, the following works just fine, with no need for bc
:
最后,使用bash
或zsh
,以下工作正常,不需要bc
:
% a=20000000
% b=C0
% printf "%X\n" $((0x$a+0x$b))
200000C0