Angenommen, man erstellt eine dynamisch benannte Variable in zsh
, und zwar folgendermaßen:
name="hello"
typeset $name=42
echo ${(P)${name}} # Prints the variable $hello, which is 42
Nehmen wir nun an, jemand möchte die besagte Variable erhöhen oder ändern, kennt jedoch nicht ihren direkten Namen. Ich würde also erwarten, dass etwas Ähnliches wie das Folgende funktioniert:
(( ${(P)${name}} = ${(P)${name}} + 1 )) # Set $hello to 43?
Das oben genannte funktioniert nicht – was sonst?
Antwort1
$ name=hello
$ hello=42
$ (($name++))
$ echo $hello
43
Genau wie in jeder Korn-ähnlichen Shell. Oder POSIXly:
$ name=hello
$ hello=42
$ : "$(($name += 1))"
$ echo "$hello"
43
Der Punkt ist, dass alle Parametererweiterungen, Befehlsersetzungen und arithmetischen Erweiterungen innerhalb arithmetischer Ausdrücke erfolgen, bevor der arithmetische Ausdruck ausgewertet wird.
((something))
ist ähnlich wie
let "something"
Also wird das in (($name++))
(wie let "$name++"
) zuerst zu erweitert hello++
und das wird als der ++
auf die hello
Variable angewendete Operator ausgewertet.
POSIX sh
hat keinen ((...))
Operator, aber die $((...))
ArithmetikErweiterungOperator. Es hat nicht ++
(obwohl es Implementierungen erlaubt, einen als Erweiterung zu haben, anstatt zu verlangen, dass es eine Kombination aus unären und/oder binären +
Operatoren sein muss), aber es hat +=
.
Durch die Verwendung des Befehls : "$((...))"
where :
is the null erhalten wir etwas Ähnliches wie ksh ((...))
. Ein striktes Äquivalent wäre jedoch [ "$((...))" -ne 0 ]
, da ((expression))
false zurückgegeben wird, wenn der Ausdruck 0 ergibt.
Antwort2
Sieht aus, als ob das hier funktioniert:
typeset $name=$(( ${(P)${name}} + 1 ))
Alle alternativen Methoden werden sehr geschätzt.