${!FOO}
выполняет двойную подстановку bash
, то есть принимает (строковое) значение FOO и использует его в качестве имени переменной.
zsh
не поддерживает эту функцию.
Есть ли способ сделать эту работу такой же в bash
и zsh
?
Фон:
У меня есть список переменных среды, как
PATH MAIL EDITOR
и хотите сначала вывести имена переменных, а затем их значения.
Это работает, bash
но не zsh
:
for VAR in LIST
do
echo $VAR
echo ${!VAR}
done
Это должно быть как-то возможно по-старому eval
, но я не могу заставить его работать:
for VAR in LIST
do
echo $VAR
echo `eval \$$VAR`
done
Я никогда не пойму, почему я не могу просто сделать произвольные глубокие замены, такие как ${${VAR}}
или даже ${${${VAR}}}
если это необходимо, поэтому объяснение этого было бы тоже неплохо.
bash
zsh
variable-substitution
for
Profpatsch
источник
источник
bash
, он действительно имеет ту же функцию (и намного больше), использует только другой шаблон, а именно${(p)FOO}
.(e)
флаг расширения параметров zsh был добавлен в zsh-2.6-beta17 (май 1996 г.),(P)
флаг в 3.1.5-pws-7 (1999 г.). Баш${!var}
в 2.0 (декабрь 1996).Ответы:
У bash и zsh есть способ выполнить косвенное расширение, но они используют другой синтаксис.
Достаточно легко выполнить косвенное расширение, используя
eval
; это работает во всех POSIX и большинстве оболочек Bourne. Будьте внимательны, чтобы правильно заключить в кавычки, если значение содержит символы, которые имеют особое значение в оболочке.${${VAR}}
не работает, потому что это не функция, которую реализует любая оболочка. Вещи внутри фигурных скобок должны соответствовать синтаксическим правилам, которые не включают${VAR}
. (В zsh это поддерживаемый синтаксис, но он делает что-то иное: вложенные подстановки выполняют последовательные преобразования для одного и того же значения;${${VAR}}
эквивалентно,$VAR
так как это выполняет преобразование идентичности дважды для значения.)источник
Комментарий под первоначальным вопросом от Profpatsch приводит пример
${(p)FOO}
вывода содержимого ссылки на косвенную переменную. Флаг неправильный или опечатка, это должен быть заглавная буква P, а не строчная буква p. Использование:${(P)FOO}
.Следующее должно дать желаемый результат:
Со страницы руководства zshexpn ; раздел - Флаги расширения параметров :
Одно время я читал, почему
${${${VAR}}}
не дает ожидаемого результата, но в настоящее время я не могу его найти. Вы можете сделать что-то вроде следующего:источник
Вы не используете eval правильно. В вашем примере значение $ VAR, которому предшествует «$» (т. Е. «$ VALUE»), будет выполнено как команда. Это не то, что вы хотите. Вы хотите оценить расширение переменной, имя которой взято из другой переменной.
источник
{ba,z}sh
решениеВот функция, которая работает в обоих {ba, z} sh. Я считаю, что это также POSIX-совместимый.
Предупреждает когда дано:
источник
function
ни[[...]]
в POSIXsh
.[ "$#" -eq 0 ]
(или, вероятно, так[ "$#" -ne 1 ]
как вы ожидаете только один аргумент).shell-check
может помочь тоже.${1-}
приведенной цитатойa='"" -o -n 1'
[ -z $a ]
==0
. Но не$#
всегда ли будет один токен?