How to increment a dynamically named variable in `zsh`

variablezsh

Say one creates a dynamically named variable in zsh, thus:

name="hello"
typeset $name=42
echo ${(P)${name}} # Prints the variable $hello, which is 42

Now, suppose one want to increment or change the said variable, but without knowing it's direct name, i.e. I'd expect something similar to the following to work:

(( ${(P)${name}} = ${(P)${name}} + 1 )) # Set $hello to 43?

The above doesn't work – what will?

Best Answer

$ name=hello
$ hello=42
$ (($name++))
$ echo $hello
43

Just like in any Korn-like shell. Or POSIXly:

$ name=hello
$ hello=42
$ : "$(($name += 1))"
$ echo "$hello"
43

The point is that all parameter expansion, command substitutions and arithmetic expansions are done inside arithmetic expressions prior to the arithmetic expression being evaluated.

((something))

is similar to

let "something"

So in (($name++)) (like let "$name++"), that's first expanded to hello++ and that's evaluated as the ++ operator applied to the hello variable.

POSIX sh has no ((...)) operator but it has the $((...)) arithmetic expansion operator. It doesn't have ++ (though it allows implementations to have one as an extension instead of requiring it to be a combination of unary and/or binary + operators), but it has +=.

By using : "$((...))" where : is the null command, we get something similar to ksh's ((...)). Though a strict equivalent would be [ "$((...))" -ne 0 ], as ((expression)) returns false when the expression resolves to 0.

Related Question