Estou lendo os primeiros quatro bytes de um arquivo binário em zsh. Os primeiros 3 bytes são 0x00
e o quarto é 0x01
. Eu criei uma matriz desses bytes lendo o arquivo como uma string e, em seguida, dividindo-o e fatiando-o, resultando em:
> echo -n "${(j::)bytes}" | xxd
00000000: 0000 0001 ....
e agora estou tentando adicioná-los começando com a extremidade direita (4º byte) usando as potências apropriadas para obter a soma. O problema é que, quando tento usar o 4º byte em uma avaliação aritmética ou uma variável inteira:
integer -i 10 b=${bytes[-1]} # This is the offending line
sum=$((sum + b * (256 ** i)))
Estou tendo o erro a seguir:
bad math expression: illegal character: ^A
Qual é 0x01
.
Como digo ao zsh para interpretar o byte como um número? Eu notei o (#)
sinalizador de expansão, que força uma expressão a ser interpretada numericamente e depois como um caractere, mas estou tendo o problema oposto. Parece estar interpretando 0x01
como um personagem.
ATUALIZAR:
Desconfio que o problema seja que o tipo do array seja de caracteres (se as coleções zsh tiverem tipos? (s::)
) elementos de volta para números inteiros. Eu tentei
b=$(printf '%d' "$bytes[4]")
mas isso me dá um erro semelhante. Eu sou capaz de reproduzir aparentemente através de qualquer um destes:
printf '%d' $'^A'
integer b=$'^A'
onde ^A
é composto pelos dois caracteres literais ^
e A
.
O
%d
operador doprintf
builtin converterá um caractere em seu valor numérico, mas precisa de uma aspa inicial para diferenciar o parâmetro de entrada de uma expressão aritmética:Observe que o valor em
b
é uma string, mesmo que tenha sido declarado comointeger
. A formatação inteira apenas altera a forma como a variável é tratada em atribuições e expansões - não altera a representação interna.Para converter uma matriz inteira de bytes, use a
-v
opção (atribuir variável) emprintf
:Algumas das peças:
typeset -a nums
- a matriz de saída. Isso é declarado como uma matriz paraprintf
atribuir cada resultado a um elemento separado da matriz. Da documentação :\'${^bin}
- isto irá prefixar cada elemento no array com uma aspa simples, usando a opção${^...}
rc_expand_param .setopt nomultibyte
- com isso, as operações do shell tratarão cada byte como um único caractere. Isso não é absolutamente necessário ao processar matrizes de bytes únicos, mas garante alguma consistência ao exibir e atribuir valores.