Как увеличить динамически именованную переменную в `zsh`

Как увеличить динамически именованную переменную в `zsh`

Допустим, мы создаем динамически именованную переменную в 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. Или POSIXly:

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

Дело в том, что все расширения параметров, подстановки команд и арифметические расширения выполняются внутри арифметических выражений до того, как арифметическое выражение будет оценено.

((something))

похож на

let "something"

Итак, в (($name++))(подобно let "$name++") это сначала расширяется до hello++и это оценивается как ++оператор, примененный к helloпеременной.

В POSIX shнет ((...))оператора, но есть $((...))арифметикарасширениеоператор. Он не имеет ++(хотя позволяет реализациям иметь его в качестве расширения вместо того, чтобы требовать, чтобы он был комбинацией унарных и/или бинарных +операторов), но имеет +=.

Используя команду : "$((...))"where :is the null, мы получаем нечто похожее на ksh's ((...)). Хотя строгим эквивалентом было бы [ "$((...))" -ne 0 ], поскольку ((expression))возвращает false, когда выражение разрешается в 0.

решение2

Похоже, это сработает:

 typeset $name=$(( ${(P)${name}} + 1 ))

Любые альтернативные методы будут высоко оценены.

Связанный контент