【问题标题】:Add two hex numbers and store as hex number in shell script添加两个十六进制数并在 shell 脚本中存储为十六进制数
【发布时间】:2018-09-19 04:37:08
【问题描述】:

我正在尝试在 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

并非所有结果都是错误的。仅当$num = C0 时出现错误

输出

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!!

我正在使用 zshell。我不确定为什么会这样。非常感谢任何帮助。

谢谢

【问题讨论】:

  • 您发布的代码不会使用shbashzsh 生成粘贴的输出。您确定您粘贴了正确的代码输出吗?
  • 有一个错字。我更正了代码。谢谢

标签: linux bash shell hex zsh


【解决方案1】:

@konsolebox 有一个正确的修复,但我认为 OP 中显示的行为有点神秘,所以似乎值得解释一下。

首先,很明显

num2=`obase=16;ibase=16; echo $start_num \\+ $num | bc`

不正确,因为它设置了 shell 变量 obaseibase,而不是将赋值传递给 bc。另外,不需要引用+。但是为什么bc 不会从 \ 中产生错误,就像该行是以现代形式编写的那样:

num2=$(obase=16;ibase=16; echo $start_num \\+ $num | bc)

答案是`…`$(…)之间存在细微差别:

% `echo echo \\+`
+
% $(echo echo \\+)
\+

引用bash manual

当使用旧式反引号形式的替换时,反斜杠保留其字面含义,除非后面跟着 $`\。前面没有反斜杠的第一个反引号终止命令替换。当使用$(command) 形式时,括号之间的所有字符组成命令;没有人受到特殊对待。

实际上,这意味着反引号版本对\-escape 进行了两次解释:第一次是在扫描反引号字符串时,当\\+ 变为\+ 时,然后第二次是在解析结果命令时, 当\+ 变成+

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

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

由于ibase 未在bc 中设置(见上文),bcC0 解释为十进制90,尽管它会将C 解释为十进制12


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

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

【讨论】:

    【解决方案2】:

    大概

    num2=`obase=16;ibase=16; echo $start_num \\+ $num | bc`
    

    应该是

    num2=`echo "obase=16;ibase=16;$start_num + $num" | bc`
    

    你根本没有计算十六进制。

    我还建议像这样的简化版本:

    #!/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
    

    它适用于 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
    

    【讨论】:

      猜你喜欢
      • 2012-10-28
      • 1970-01-01
      • 2013-09-23
      • 2010-09-27
      • 2013-10-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多