次のように、 で動的に名前が付けられた変数を作成するとしますzsh
。
name="hello"
typeset $name=42
echo ${(P)${name}} # Prints the variable $hello, which is 42
さて、上記の変数を増分または変更したいが、その直接の名前がわからない場合、次のようなものが機能すると予想されます。
(( ${(P)${name}} = ${(P)${name}} + 1 )) # Set $hello to 43?
上記は機能しません。何が機能するのでしょうか?
答え1
$ name=hello
$ hello=42
$ (($name++))
$ echo $hello
43
Korn のようなシェルと同じです。または POSIX の場合:
$ name=hello
$ hello=42
$ : "$(($name += 1))"
$ echo "$hello"
43
重要なのは、すべてのパラメータ展開、コマンド置換、および算術展開が、算術式が評価される前に算術式内で実行されることです。
((something))
と類似しています
let "something"
したがって、(($name++))
( のようにlet "$name++"
) では、まず が に展開されhello++
、それが変数++
に適用された演算子として評価されますhello
。
POSIXには演算子sh
はないが、算術演算子((...))
はある。$((...))
拡大演算子。 はありませんが++
(ただし、実装では、単項演算子や二項演算子の組み合わせを要求する代わりに、拡張として 1 つを含めることができます+
)、 はあります+=
。
: "$((...))"
whereが null コマンドである場合、を使用すると:
、ksh の に似たものが得られます((...))
。 厳密に同等のものは ですが[ "$((...))" -ne 0 ]
、((expression))
式が 0 に解決されると は false を返します。
答え2
次のようにすれば解決するようです:
typeset $name=$(( ${(P)${name}} + 1 ))
代替の方法があれば、ぜひ教えてください。