${!FOO}
executa uma substituição dupla em bash
, o que significa que pega o valor (string) de FOO e o usa como um nome de variável.
zsh
não suporta esse recurso.
Existe uma maneira de fazer isso funcionar da mesma maneira bash
e zsh
?
Fundo:
Eu tenho uma lista de variáveis de ambiente, como
PATH MAIL EDITOR
e deseja primeiro imprimir os nomes das variáveis e depois seus valores.
Isso funciona, bash
mas não zsh
:
for VAR in LIST
do
echo $VAR
echo ${!VAR}
done
Deveria ser de alguma forma possível "do jeito antigo" eval
, mas não consigo fazer isso funcionar:
for VAR in LIST
do
echo $VAR
echo `eval \$$VAR`
done
Eu nunca vou entender por que não posso simplesmente fazer substituições profundas arbitrárias como ${${VAR}}
ou mesmo ${${${VAR}}}
se necessário, então uma explicação para isso também seria legal.
bash
zsh
variable-substitution
for
Profpatsch
fonte
fonte
bash
, ele realmente tem a mesma função (e muito mais), apenas usa um padrão diferente, a saber${(p)FOO}
.(e)
sinalizador de expansão de parâmetro do zsh foi adicionado no zsh-2.6-beta17 (maio de 1996), o(P)
sinalizador em 3.1.5-pws-7 (1999). bash's${!var}
em 2.0 (dezembro de 1996).Respostas:
Tanto o bash quanto o zsh têm uma maneira de executar expansão indireta, mas usam sintaxe diferente.
É fácil o suficiente para executar expansão indireta usando
eval
; isso funciona em todos os shell POSIX e na maioria dos Bourne. Lembre-se de citar corretamente, caso o valor contenha caracteres que tenham um significado especial no shell.${${VAR}}
não funciona porque não é um recurso que qualquer shell implemente. A coisa dentro dos chavetas deve estar em conformidade com as regras de sintaxe que não incluem${VAR}
. (No zsh, isso é suportado pela sintaxe, mas faz algo diferente: substituições aninhadas executam transformações sucessivas no mesmo valor;${${VAR}}
é equivalente a$VAR
uma vez que isso executa a transformação de identidade duas vezes no valor.)fonte
O comentário, sob a pergunta original, de Profpatsch, fornece o exemplo
${(p)FOO}
para gerar o conteúdo de uma referência variável indireta. O sinalizador está incorreto ou é um erro de digitação, deve ser um P maiúsculo e não um p minúsculo. Use:${(P)FOO}
.O seguinte deve produzir a saída desejada:
Na página do manual zshexpn ; seção - Sinalizadores de expansão de parâmetro :
Ao mesmo tempo, li por
${${${VAR}}}
que não produz a saída que você esperava, mas neste momento não consigo encontrá-la. Você pode fazer algo como o seguinte:fonte
Você não está usando o eval corretamente. No seu exemplo, o valor de $ VAR precedido por um "$" (ou seja, `$ VALUE ') seria executado como um comando. Não é isso que você quer. Você deseja avaliar a expansão de uma variável cujo nome é obtido de outra variável.
fonte
{ba,z}sh
soluçãoAqui está uma função que funciona em ambos {ba, z} sh. Acredito que também seja compatível com POSIX.
Ele avisa quando dado:
fonte
function
nem[[...]]
no POSIXsh
.[ "$#" -eq 0 ]
(ou provavelmente[ "$#" -ne 1 ]
como você espera apenas um argumento).shell-check
pode ajudar também.${1-}
dadaa='"" -o -n 1'
[ -z $a ]
==0
. Mas nem$#
sempre será um único token?