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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-18 10:36:45  来源:igfitidea点击:

Add two hex numbers and store as hex number in shell script

linuxbashshellhexzsh

提问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 obaseand ibaserather than passing the assignment to bc. Also, it's unnecessary to quote the +. But why doesn't bcproduce an error from the \, as it would if the line had been written in the modern form:

不正确,因为它是设置shell变量obaseibase而不是传递分配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 bashmanual:

引用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 bcinterprets numbers. It's worth quoting the full paragraph from man bc(emphasis added):

第二个问题是“20000090从哪里来?” 答案是,这是bc解释数字方式的一个奇怪特征。值得引用完整的段落man bc(强调添加):

Input numbers may contain the characters 0-9and A-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 of ibase. (i.e. A = 10.) For multi-digit numbers, bcchanges all input digits greater or equal to ibaseto the value of ibase-1.This makes the number FFFalways be the largest 3 digit number of the input base.

输入数字可能包含字符0-9A-F。(注意:它们必须是大写的。小写字母是变量名。)无论 的值如何,单个数字始终具有该数字的值ibase。(即A = 10。) 对于多位数字,bc将所有输入数字更改为大于或等于ibase的值ibase-1这使得数字FFF始终是输入基数的最大 3 位数字。

Since ibasewas not set in bc(see above), bcinterprets C0as decimal 90, although it would have interpreted Cas decimal 12.

由于ibase未设置bc(见上文),bc解释C0为 decimal 90,尽管它会解释C为 decimal 12



Finally, with either bashor zsh, the following works just fine, with no need for bc:

最后,使用bashzsh,以下工作正常,不需要bc

% a=20000000
% b=C0
% printf "%X\n" $((0x$a+0x$b))
200000C0