Digamos que alguém crie uma variável nomeada dinamicamente em zsh
, assim:
name="hello"
typeset $name=42
echo ${(P)${name}} # Prints the variable $hello, which is 42
Agora, suponha que alguém queira incrementar ou alterar a referida variável, mas sem saber seu nome direto, ou seja, eu esperaria que algo semelhante ao seguinte funcionasse:
(( ${(P)${name}} = ${(P)${name}} + 1 )) # Set $hello to 43?
O que foi dito acima não funciona - o que funcionará?
Responder1
$ name=hello
$ hello=42
$ (($name++))
$ echo $hello
43
Assim como em qualquer shell do tipo Korn. Ou POSIXly:
$ name=hello
$ hello=42
$ : "$(($name += 1))"
$ echo "$hello"
43
A questão é que todas as expansões de parâmetros, substituições de comandos e expansões aritméticas são feitas dentro de expressões aritméticas antes da expressão aritmética ser avaliada.
((something))
é similar a
let "something"
Então, em (($name++))
(como let "$name++"
), isso é primeiro expandido para hello++
e avaliado como o ++
operador aplicado à hello
variável.
POSIX sh
não tem ((...))
operador, mas tem $((...))
aritméticaexpansãooperador. Ele não possui ++
(embora permita que as implementações tenham um como extensão em vez de exigir que seja uma combinação de +
operadores unários e/ou binários), mas possui +=
.
Usando : "$((...))"
where :
is o comando null, obtemos algo semelhante ao ksh's ((...))
. Embora um equivalente estrito fosse [ "$((...))" -ne 0 ]
, as ((expression))
retorna falso quando a expressão é resolvida como 0.
Responder2
Parece que isso vai resolver:
typeset $name=$(( ${(P)${name}} + 1 ))
Quaisquer métodos alternativos serão muito apreciados.