Variáveis ​​do shell de pesquisa por nome, indiretamente

Digamos que eu tenha o nome de uma variável armazenado em outra variável:

myvar=123 varname=myvar 

Agora, gostaria de obter o 123 usando apenas a variável $ varname. Existe um caminho direto para isso? Eu não encontrei nenhum tal bash builtin para pesquisa pelo nome, então surgiu com isso:

 function var { v="\$$1"; eval "echo "$v; } 

assim

 var $varname # gives 123 

O que não parece tão ruim no final, mas estou me perguntando se perdi algo mais óbvio. Desde já, obrigado!

Na página man do bash :

 ${!varname} 

Se o primeiro caractere do parâmetro for um ponto de exclamação, um nível de indireto de variável será introduzido. Bash usa o valor da variável formada a partir do resto do parâmetro como o nome da variável; essa variável é então expandida e esse valor é usado no restante da substituição, em vez do valor do próprio parâmetro. Isso é conhecido como expansão indireta.

Não existe uma syntax direta em conformidade com o Posix, apenas um bash ism. Eu costumo fazer isso:

 eval t="\$$varname" 

Isso funcionará em qualquer shell Posix, incluindo aqueles sistemas em que o bash é o shell de login e /bin/sh é algo menor e mais rápido como o ash . Eu gosto de bash e usá-lo para o meu shell de login, mas eu evito bashisms em arquivos de comando.


Nota: Um problema com a escrita de scripts específicos do bash é que mesmo se você puder contar com o bash sendo instalado, ele pode estar em qualquer lugar no caminho. Pode ser uma boa idéia, nesse caso, usar o estilo shebang /usr/bin/env totalmente geral, mas observe que isso ainda não é 100% portátil e tem problemas de segurança.

${!varname} deve fazer o truque

 $ var="content" $ myvar=var $ echo ${!myvar} content 

Eu costumo olhar para o Advance Bash-Scripting Guide quando eu precisar atualizar minhas habilidades Bash.

Em relação à sua pergunta, consulte Referências Indiretas

A notação é:

 Version < 2 \$$var Version >= 2 ${!varname} 
 # bmuSetIndirectVar() # TO DOUBLE CHECK THIS COMMENT AND DEMO # This function is an helper to read indirect variables. # ie get the content of a variable whose name is saved # within an other variable. Like: # MYDIR="/tmp" # WHICHDIR="MYDIR" # bmuSetIndirectVar "WHICHDIR" "$MYDIR" # bmuSetIndirectVar(){ tmpVarName=$1 locVarName=$1 extVarName=$2 #echo "debug Ind Input >$1<>$2< " eval tmpVarName=\$$extVarName #echo "debug Ind Output >$tmpVarName<>$extVarName< " export $locVarName="${tmpVarName}" } 

Atualmente estou usando essa pequena function. Eu não estou totalmente feliz com isso, e tenho visto soluções diferentes na web (se me lembro eu as escreveria aqui), mas parece funcionar. Dentro dessas poucas linhas já existe alguma redundância e dados extras, mas foi útil para a debugging.

Se você quiser vê-lo no lugar, ou seja, onde eu estou usando, verifique: https://github.com/mariotti/bmu/blob/master/bin/backmeup.shellfunctions.sh

É claro que não é a melhor solução, mas me fez continuar com o trabalho, na esperança de poder substituí-lo por algo um pouco mais geral em breve.