我正在 zsh 中读取二进制文件的前四个字节。前 3 个字节是0x00
,第四个字节是0x01
。我通过将文件作为字符串读取,然后将其分割并切片,创建了这些字节的数组,结果是:
> echo -n "${(j::)bytes}" | xxd
00000000: 0000 0001 ....
现在我尝试使用适当的幂从右端(第 4 个字节)开始将它们相加以获得总和。问题是,当我尝试在算术评估或整数变量中使用第四个字节时:
integer -i 10 b=${bytes[-1]} # This is the offending line
sum=$((sum + b * (256 ** i)))
我收到以下错误:
bad math expression: illegal character: ^A
这是0x01
.
如何告诉 zsh 将字节解释为数字?我注意到(#)
扩展标志,它强制将表达式解释为数字,然后解释为字符,但我遇到了相反的问题。它似乎被解释0x01
为一个角色。
更新:
我怀疑问题是数组的类型是字符(如果 zsh 集合有类型?),因为我使用(s::)
整个文件的字符串创建了它,但我不确定如何转换数组元素返回整数。我尝试过
b=$(printf '%d' "$bytes[4]")
但这给了我一个类似的错误。我似乎可以通过以下任何一种方式重现:
printf '%d' $'^A'
integer b=$'^A'
其中由两个文字字符和^A
组成。^
A
%d
内置的运算符会将printf
字符转换为其数值,但它需要一个前导引号来区分输入参数和算术表达式:请注意,中的值
b
是一个字符串,即使它被声明为integer
. 整数排版仅更改变量在赋值和扩展中的处理方式 - 它不会更改内部表示。要转换整个字节数组,请使用
-v
(分配变量) 选项printf
:部分作品:
typeset -a nums
- 输出数组。这被声明为一个数组,以便printf
将每个结果分配给一个单独的数组元素。从 文档中:\'${^bin}
${^...}
- 这将使用rc_expand_param选项为数组中的每个元素添加单引号前缀。setopt nomultibyte
- 这样,shell 操作会将每个字节视为单个字符。在处理单字节数组时,这并不是绝对必要的,但它可以确保显示和分配值时的一定一致性。